c++ - Socket chat system - broadcasting them to all clients -
communication between server , clients works, server don't forward client messages other connected client's, sender.
i want server react incoming messages broadcasting them clients chat system, keep command system without sharring clients, with sender.
down below sources:
server
/*server*/ #define win32_lean_and_mean #include <iostream> #include <string> #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <stdlib.h> #include <stdio.h> #include <process.h> // need link ws2_32.lib, mswsock.lib, , advapi32.lib #pragma comment (lib, "ws2_32.lib") #pragma comment (lib, "mswsock.lib") #pragma comment (lib, "advapi32.lib") #define port "3490" #define server "localhost" #include <time.h> wsadata wsa; socket s , new_socket; struct sockaddr_in server , client; int c; char *message; std::string line; dword winapi processclient (lpvoid lpparameter) { socket acceptsocket = (socket) lpparameter; // send , receive data. int bytessent; int bytesrecv = socket_error; char sendbuf[2000]=""; char sendbuf2[2000]=""; char recvbuf[2000]=""; char timebuf[128]; sprintf(sendbuf, "hello, it's test server @ %s:%d (commands: 1, 2, exit)\n", server, port); bytessent = send( acceptsocket, sendbuf, strlen(sendbuf), 0); if (bytessent == socket_error) { printf( "error @ send hello: %ld\n", wsagetlasterror()); goto fin; } while (1) { _strtime( timebuf ); zeromemory (recvbuf, sizeof(recvbuf)); bytesrecv = recv( acceptsocket, recvbuf, 32, 0); printf( "%s client said: %s\n", timebuf, recvbuf); sprintf(sendbuf, "%s client said: %s\n", timebuf, recvbuf); bytessent = send( acceptsocket, sendbuf, strlen(sendbuf), 0); if (strcmp(recvbuf, "1") == 0) { sprintf(sendbuf, "you typed one\n"); //printf("sent '%s'\n", sendbuf); bytessent = send( acceptsocket, sendbuf, strlen(sendbuf), 0); if (bytessent == socket_error) { printf( "error @ send: %ld\n", wsagetlasterror()); goto fin; } } else if (strcmp(recvbuf, "2") == 0) { sprintf(sendbuf, "you typed two\n"); //printf("sent '%s'\n", sendbuf); bytessent = send( acceptsocket, sendbuf, strlen(sendbuf), 0); if (bytessent == socket_error) { printf( "error @ send: %ld\n", wsagetlasterror()); goto fin; } } else if (strcmp(recvbuf, "exit") == 0) { printf( "client has logged out\n", wsagetlasterror()); goto fin; } else { // sprintf(sendbuf, "unknown command\n"); //printf("sent '%s'\n", sendbuf); // bytessent = send( acceptsocket, sendbuf, strlen(sendbuf), 0); if (bytessent == socket_error) { // printf( "error @ send: %ld\n", wsagetlasterror()); goto fin; } } } fin: printf("client processed\n"); closesocket(acceptsocket); return 0; } int main(int argc , char *argv[]) { std::cout << ("\ninitialising winsock..."); if (wsastartup(makeword(2,2),&wsa) != 0) { std::cout << ("failed. error code : %d",wsagetlasterror()); return 1; } printf("initialised.\n"); //create socket if((s = socket(af_inet , sock_stream , 0 )) == invalid_socket) { std::cout << ("could not create socket : %d" , wsagetlasterror()); } std::cout << ("socket created.\n"); //prepare sockaddr_in structure server.sin_family = af_inet; server.sin_addr.s_addr = inaddr_any; server.sin_port = htons( 3490 ); //bind if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == socket_error) { std::cout << ("bind failed error code : %d" , wsagetlasterror()); exit(exit_failure); } puts("bind done"); //listen incoming connections listen(s , 3); //accept , incoming connection std::cout << ("waiting incoming connections..."); c = sizeof(struct sockaddr_in); while(true){ while((new_socket = accept(s , (struct sockaddr *)&client, &c)) != invalid_socket) { // create new thread accepted client (also pass accepted client socket). printf( "client connected.\n"); dword dwthreadid; createthread (null, 0, processclient, (lpvoid) new_socket, 0, &dwthreadid); } } if (new_socket == invalid_socket) { std::cout << ("accept failed error code : %d" , wsagetlasterror()); return 1; } closesocket(s); wsacleanup(); return 0; } client
/*client*/ #define win32_lean_and_mean #pragma comment(lib,"ws2_32.lib") #include <iostream> #include <process.h> #include <string> #include <winsock2.h> socket socket; #define server "localhost" int port = 3490; std::string line; bool chat = false; class buffer { public: int id; char message[256]; }sbuffer; int clientthread() { char buffer[2000]= ""; for(;; sleep(10)) { if(recv(socket, buffer, sizeof(sbuffer), null)!=socket_error) { strncpy(sbuffer.message, buffer, sizeof(sbuffer.message)); std::cout << "<client:" << sbuffer.id << ":> " << sbuffer.message <<std::endl; zeromemory (buffer, sizeof(buffer)); } } return 0; } int main(void) { wsadata wsadat; if(wsastartup(makeword(2,2),&wsadat)!=0) { std::cout<<"winsock error - winsock initialization failed\r\n"; wsacleanup(); system("pause"); return 0; } // create our socket socket=socket(af_inet,sock_stream,ipproto_tcp); if(socket==invalid_socket) { std::cout<<"winsock error - socket creation failed!\r\n"; wsacleanup(); system("pause"); return 0; } // resolve ip address hostname struct hostent *host; if((host=gethostbyname(server))==null) { std::cout<<"failed resolve hostname.\r\n"; wsacleanup(); system("pause"); return 0; } // setup our socket address structure sockaddr_in sockaddr; sockaddr.sin_port=htons(port); sockaddr.sin_family=af_inet; sockaddr.sin_addr.s_addr=*((unsigned long*)host->h_addr); // attempt connect server if(connect(socket,(sockaddr*)(&sockaddr),sizeof(sockaddr))!=0) { std::cout<<"failed establish connection server\r\n"; wsacleanup(); system("pause"); return 0; } // if imode!=0, non-blocking mode enabled. u_long imode=1; ioctlsocket(socket,fionbio,&imode); // main loop for(;;) { // display message server char buffer[1000]; memset(buffer,0,999); int indatalength=recv(socket,buffer,1000,0); std::cout<<buffer; createthread(null, null, (lpthread_start_routine) clientthread, null, null, null); for(;; sleep(10)) { std::string buffer; std::getline(std::cin, buffer); if (send(socket, buffer.c_str(), buffer.length(), null) < 1){ } } int nerror=wsagetlasterror(); if(nerror!=wsaewouldblock&&nerror!=0) { std::cout<<"winsock error code: "<<nerror<<"\r\n"; std::cout<<"server disconnected!\r\n"; // shutdown our socket shutdown(socket,sd_send); // close our socket entirely closesocket(socket); break; } sleep(1000); } wsacleanup(); system("pause"); return 0; } please me fix it, i'm new socket's. show me how i'm going understand better code , usefull others might need in future.
if need server communicate multiple clients, need kind of collection of connected clients. it's easy send connections, or send connection originating connection.
how differ vastly between c , c++, c++ structures , std::vector.
in pseudo-code this:
while (run_server) { poll_all_connections(); if (have_new_connection()) { accept_new_connection(); add_connection_in_collection(); } else { (connection in all_connections()) { if (have_input(connection)) { input = read_from_connection(connection); (send_to in all_connections()) write_to_connection(connection, input) } } } } if implement above pseudo-code, input connection sent connections.
don't forget remove connection collection if connection broken (error or disconnect.)
Comments
Post a Comment