Thread: recieve data, then send data to all other clients

  1. #1
    Registered User
    Join Date
    Apr 2004
    Posts
    102

    recieve data, then send data to all other clients

    i have just slightly modified the code from gametutorials.com on allowing multiple connections to a server. what i tried to do with this code is, when a client sends a message to the server the server sends that message to all other clients connected to the server. I thought that this code would work:

    Code:
    #pragma comment(lib, "wsock32.lib")
    #include <winsock.h>
    #include <windows.h>
    int startupServerForListening(unsigned short port);
    void shutdownServer(int socket);
    HANDLE threadHandle;
    HANDLE mutexHandle;
    FD_SET allsockets;
    bool gQuitFlag = false;
    
    void acceptingThreadProcedure(int* serverSocket) {
    	
    	int mySocket = *serverSocket;
    	
    	for (;;) {
    		unsigned int clientSocket = accept(mySocket, 0, 0);
    		
    		if (clientSocket == SOCKET_ERROR) {
    			MessageBox(0,"Accept Failed!","",0);
    			gQuitFlag = true;
    			return;
    			
    		} else {
    			
    			WaitForSingleObject(mutexHandle, INFINITE);
    			FD_SET(clientSocket, &allsockets);
    			ReleaseMutex(mutexHandle);
    			MessageBox(0,"Client Connected","",0);
    		}
    	}
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    				   LPSTR lpCmdLine, int nCmdShow){
    	int serverSocket;
    	
    	serverSocket = startupServerForListening(7654);
    	
    	if (serverSocket == -1) {
    		MessageBox(0,"ERROR","",0);
    		return 0;
    	}
    	mutexHandle = CreateMutex(NULL, false, NULL);
    	if (mutexHandle == NULL) {
    		MessageBox(0,"Error creating mutex","",0);
    		shutdownServer(serverSocket);
    		return 0;
    	}
    	int threadId;
    	threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)acceptingThreadProcedure, &serverSocket, 0, (LPDWORD)&threadId);
    	if (threadHandle == NULL) {
    		MessageBox(0,"ERROR STARTING LISTENING THREAD","",0);
    		shutdownServer(serverSocket);
    		return 0;
    	}
    	Sleep(1000);
    	FD_ZERO(&allsockets);
    	
    	for (;;) {
    		if (gQuitFlag) {
    			break;
    		}
    		Sleep(400);
    		
    		WaitForSingleObject(mutexHandle, INFINITE);
    		FD_SET tmpallsockets = allsockets;
    		ReleaseMutex(mutexHandle);
    		if (tmpallsockets.fd_count == 0) {
    			continue;
    		}
    		timeval waitTime;
    		waitTime.tv_sec = 0;
    		waitTime.tv_usec = 0;
    		int result = select(tmpallsockets.fd_count, &tmpallsockets, NULL, NULL, &waitTime);
    		if (result == 0) {
    			continue;
    		}
    		
    		if (result == SOCKET_ERROR) {
    			MessageBox(0,"ERROR IN SELECT", "",0);
    			continue;
    		}
    		
    		for (unsigned int i = 0; i < tmpallsockets.fd_count; i++) {
    			
    			unsigned int clientSocket = tmpallsockets.fd_array[i];
    			int nBytes;
    #define MAX_MESSAGE_SIZE 4096
    			char buffer[MAX_MESSAGE_SIZE];
    			
    			nBytes = recv(clientSocket, buffer, sizeof(buffer), 0);
    			if (nBytes == SOCKET_ERROR) {
    				int error = WSAGetLastError();
    				if (error == WSAECONNRESET) {
    					WaitForSingleObject(mutexHandle, INFINITE);
    					FD_CLR(clientSocket, &allsockets);
    					ReleaseMutex(mutexHandle);
    					closesocket(clientSocket);
    					
    					MessageBox(0,"A client disconnected","",0);
    					
    					continue;
    					
    				} else {
    					MessageBox(0,"SEND FAILED, SERVER TERMINATING","",0);
    					gQuitFlag = true;
    					break;
    					
    				}
    			}
    			if (nBytes == 0) {
    				WaitForSingleObject(mutexHandle, INFINITE);
    				FD_CLR(clientSocket, &allsockets);
    				ReleaseMutex(mutexHandle);
    				closesocket(clientSocket);
    				MessageBox(0,"A CLIENT DISCONNECTED","",0);
    				continue;
    			}
    			buffer[sizeof(buffer)] = '\0';
    			for (i=0; i < tmpallsockets.fd_count; i++) {
    				unsigned int clientSocketout = tmpallsockets.fd_array[i];
    				if(clientSocket == SOCKET_ERROR){
    					MessageBox(0,"error","",0);
    				}
    				nBytes = send(clientSocketout, buffer, sizeof(buffer), 0);
    				MessageBox(0,"message sent","",0);
    				if (nBytes == SOCKET_ERROR) {
    					int error = WSAGetLastError();
    					if (error == WSAECONNRESET) {
    						WaitForSingleObject(mutexHandle, INFINITE);
    						FD_CLR(clientSocket, &allsockets);
    						ReleaseMutex(mutexHandle);
    						closesocket(clientSocket);
    						
    						MessageBox(0,"A client disconnected","",0);
    						
    						continue;
    						
    					} else {
    						MessageBox(0,"SEND FAILED, SERVER TERMINATING","",0);
    						gQuitFlag = true;
    						break;
    						
    					}
    				}
    				if (nBytes == 0) {
    					WaitForSingleObject(mutexHandle, INFINITE);
    					FD_CLR(clientSocket, &allsockets);
    					ReleaseMutex(mutexHandle);
    					closesocket(clientSocket);
    					MessageBox(0,"A CLIENT DISCONNECTED","",0);
    					continue;
    				}
    				
    			}
    		}
    	}
    	shutdownServer(serverSocket);
    	return 0;
    }
    
    int startupServerForListening(unsigned short port) {
        int error;
    	WSAData wsaData;
    	if ((error = WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR) {
    		return -1;
    	}
    	int mySocket = socket(AF_INET, SOCK_STREAM, 0);
    	if (mySocket == SOCKET_ERROR) {
    		return -1;
    	}
    	struct sockaddr_in server;
    	server.sin_family = AF_INET;
    	server.sin_port = htons(port);
    	server.sin_addr.s_addr = INADDR_ANY;
    	if (bind(mySocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
    		closesocket(mySocket);
    		return -1;
    	}
    	if (listen(mySocket, 5) == SOCKET_ERROR) {
    		closesocket(mySocket);
    		return -1;
    	}
    	
    	return mySocket;
    }
    
    void shutdownServer(int socket) {
    	
    	WaitForSingleObject(threadHandle, INFINITE);
    	CloseHandle(threadHandle);
    	CloseHandle(mutexHandle);
    	closesocket(socket);
    	WSACleanup();
    }
    but it doesn't, it recieves the message from a client then sends that same message back to the client that sent it, but to nobody else, just the client that sent it. and i really don't know why it's doing it.
    Could you please tell me why it's doing what it is?

  2. #2
    Registered User
    Join Date
    Apr 2004
    Posts
    102
    thats another day i just spent trying to fix this, it just wont work? does anybody have any idea at all, or even a hint to why it's not working?
    please, i'm desperate here.

  3. #3
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    What you're trying to do is shown here:
    http://www.ecst.csuchico.edu/~beej/g...selectserver.c
    Its a *nix orientated version, but the logic still applies to yours. hth.

    >>buffer[sizeof(buffer)] = '\0';
    This is a buffer overflow
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  4. #4
    Registered User
    Join Date
    Apr 2004
    Posts
    102
    thanks for the link, but i couldn't understand some of it, the problem is that, i really do see that big of a difference between the codes, i changed some of my code and now the program is less functional than it was before.

  5. #5
    Registered User
    Join Date
    Apr 2004
    Posts
    102
    i thought i had cracked it last night, when i thought of this code:

    Code:
    int x=0;
    			while(tmpallsockets.fd_array[x] != NULL){
    				send(tmpallsockets.fd_array[x], buffer, sizeof(buffer),0);
    				x++;
    			}
    			x=0;
    but what happens now is that, if there are 2 people connected and a client sends a message, it sends the message back to the same client twice, and if three clients are connected it sends same message to the client who sent it 3 times... i'm really confused. what could possibly be the problem?
    how can all the sockets in the socket array be the same client?

  6. #6
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    When you loop through the array to "send" the message, which array should you be looping through? The tmpallsockets array that has only the sockets with read state set, or the allsockets array that contains all of the connected clients?

    Make sure you don't send back to the originator by doing something like:
    Code:
     unsigned int  clientSocketout = allsockets.fd_array[i];
     if (clientSocketout == clientSocket)
               continue;
    And you should sent the same amount of data that you received:
    Code:
     SentBytes = send(clientSocketout, buffer, nBytes, 0);
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  7. #7
    Registered User
    Join Date
    Apr 2004
    Posts
    102
    thanks man, got it working now
    cheers

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. data structure design for data aggregation
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 05-20-2008, 06:43 AM
  2. HUGE fps jump
    By DavidP in forum Game Programming
    Replies: 23
    Last Post: 07-01-2004, 10:36 AM
  3. Post programs
    By GaPe in forum C# Programming
    Replies: 8
    Last Post: 05-12-2002, 11:07 AM
  4. gcc problem
    By bjdea1 in forum Linux Programming
    Replies: 13
    Last Post: 04-29-2002, 06:51 PM
  5. Replies: 2
    Last Post: 03-05-2002, 05:52 AM