Thread: Receive multiple data- client- server

  1. #1
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715

    Receive multiple data- client- server

    Hello,

    what should I need to change in (I assume) server code to receive
    more than one sentence that I seand from Client application.
    Here's code:

    Client:
    Code:
    #include <iostream>
    #include <winsock2.h>
    #include <windows.h>
    #include <cstring>
    
    #define PORT 5193
    #define Version 0x0002
    #define BUFFER_SIZE 1024
    char hostname[]="localhost";
    char *menu[]={"1. Send data\n","2. End session\n","Your choice: "};
    
    int main()
    {	
    	char msg[BUFFER_SIZE];
    	WSADATA wsaData;
    	SOCKET sServer;
    	SOCKADDR_IN ServerSockAddr;
    	hostent* pHost;
    	protoent* pProtocol;
    	
    
    
    	WSAStartup(Version,&wsaData);
    
    	ZeroMemory((void*)&ServerSockAddr,sizeof(ServerSockAddr));
    	
    	pHost=gethostbyname(hostname);
    	if(pHost==NULL)
    	{
    		std::cout<<"Error! Cannot get host infos!"<<std::endl;
    		return 1;
    	}
    	
    	ServerSockAddr.sin_family=AF_INET;
    	ServerSockAddr.sin_port=htons(PORT);
    	memcpy(&ServerSockAddr.sin_addr,pHost->h_addr,pHost->h_length);
    	
    	pProtocol=getprotobyname("tcp");
    	if(pProtocol==NULL)
    	{
    		std::cout<<"Error! Cannot get protocol infos!"<<std::endl;
    		return 1;
    	}
    
    	sServer=socket(AF_INET,SOCK_STREAM,pProtocol->p_proto);
    	if(sServer==INVALID_SOCKET)
    	{
    		std::cout<<"Error! Cannot create socket!"<<std::endl;
    		return 1;
    	}
    
    	if(connect(sServer,(const sockaddr*)&ServerSockAddr,sizeof(sockaddr))==SOCKET_ERROR)
    	{
    		std::cout<<"Error! Cannot connect!"<<std::endl;
    		return 1;
    	}
    	
    	int end=7;
    	do
    	{
    		
    		std::cout<<menu[0];
    		std::cout<<menu[1];
    		std::cout<<menu[2];
    		std::cin>>end;
    
    		switch(end)
    		{
    		case 1:
    			{
    				std::cin.clear();
    				std::cin.ignore(BUFFER_SIZE, '\n');
    				std::cout<<"Enter sentence to send: "; 
    				std::cin.getline(msg,BUFFER_SIZE,'\n');
    				
    				send(sServer,msg,(int)strlen(msg)+1,0);
    			}
    			break;
    		case 2:
    			break;
    		default:
    			std::cout<<"Wrong choice"<<std::endl;
    		}
    
    	}while(end !=2);
    
    	closesocket(sServer);
    	WSACleanup();
    	return 0;
    }

    Server:
    Code:
    #include <iostream>
    #include <winsock2.h>
    #include <windows.h>
    
    #define PORT 5193
    #define MAX_CON 5
    #define BUFFER_SIZE 1024
    #define Version 0x0002
    
    int main()
    {
    	SOCKADDR_IN ServerSockAddr,ClientSockAddr;
    	struct protoent* pProtocolInfo;
    	SOCKET sServer,sClient;
    	int aLen;
    	char msg [BUFFER_SIZE];
    	WSADATA wsaData;
    	WSAStartup(Version,&wsaData);
    	ZeroMemory((void*)&ClientSockAddr,sizeof(ClientSockAddr));
    	ZeroMemory((void*)&ServerSockAddr,sizeof(ServerSockAddr));
    
    	ServerSockAddr.sin_family=AF_INET;//stays in host byte order
    	ServerSockAddr.sin_port=htons(PORT);//network byte order
    	ServerSockAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//network byte order
    	
    	if((pProtocolInfo=getprotobyname("tcp"))==0)
    	{
    		std::cout<<"Error! Cannot get protocol info!"<<std::endl;
    		return 1;
    	}
    	//Creating socket
    	sServer=socket(AF_INET,SOCK_STREAM,pProtocolInfo->p_proto);
    	if(sServer==INVALID_SOCKET)
    	{
    		std::cout<<"Error! Cannot create server socket!"<<std::endl;
    		return 1;
    	}
    	
    	//Binding socket
    	if(bind(sServer,(const sockaddr *)&ServerSockAddr,sizeof(sockaddr))==SOCKET_ERROR)
    	{
    		std::cout<<"Error! Cannot bind server socket!"<<std::endl;
    		return 1;
    	}
    	
    	//Listening for incomming connections
    	if(listen(sServer,MAX_CON)==SOCKET_ERROR)
    	{
    		std::cout<<"Error! Cannot listen for incomming! connections"<<std::endl;
    		return 1;
    	}
    	std::cout<<"Listening for incomming connections!"<<std::endl;
    
    	aLen=sizeof(ClientSockAddr);
    	while(true)
    	{
    		int get;
    		sClient=accept(sServer,(sockaddr*)&ClientSockAddr,&aLen);
    		if(sClient==SOCKET_ERROR)
    		{
    			std::cout<<"Error! Cannot accept connection"<<std::endl;
    			return 1;
    		}
    
    		get=recv(sClient,msg,BUFFER_SIZE,0);
    		if(get==SOCKET_ERROR)
    		{
    			std::cout<<"Receiving error!"<<std::endl;
    			return 1;
    		}
    		if(get==0)
    		{
    			std::cout<<"Transmission ended!"<<std::endl;
    			break;
    		}
    		else
    		{
    			std::cout<<msg<<std::endl;
    			continue;
    		}
    
    	}
    	closesocket(sServer);
    	closesocket(sClient);
    	WSACleanup();
    	return 0;
    }
    When I send first sentence, it is shown in server application, but every other sentence are ignored
    Why?

    Thanks for help!

  2. #2
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    I can solve this by moving code:
    Code:
    int get;
    		sClient=accept(sServer,(sockaddr*)&ClientSockAddr,&aLen);
    		if(sClient==SOCKET_ERROR)
    		{
    			std::cout<<"Error! Cannot accept connection"<<std::endl;
    			return 1;
    		}
    before while(true),
    but then my server program finish when client finish sending data.
    How to make my server contionues listening after client is done??
    I really don't have much experience in network programming so any help is welcome

  3. #3
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    The problem is that the accept() function is blocking any processing after the first iteration of the while loop after the first client connects. Essentially, it is simply waiting for another connection and once it's received, your server will no longer be able to communicate with the previous client.

    Your solution is to make your application multithreaded, use asynchronous sockets, or just do any necessary communication with the client in a single series of predetermined steps then close the connection.

  4. #4
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    Thanks for reply Lucky, basicaly I know what I should do, but don't know how. I've just started recenty to learn multithreading.
    How complicate would be to change existing code I posted here?

    Can you tell me more or give link to a good tutorial or explanation on asynchronous sockets. I'm not sure what is it. In my tutorial I learnd just about socket never mentioning asynchronous sockets or some other types.
    Thanks

  5. #5
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    I manage to so something. Here's code:

    Code:
    #include <iostream>
    #include <winsock2.h>
    #include <windows.h>
    
    #define PORT 5193
    #define MAX_CON 5
    #define BUFFER_SIZE 1024
    #define Version 0x0002
    
    int main()
    {
    	SOCKADDR_IN ServerSockAddr,ClientSockAddr;
    	struct protoent* pProtocolInfo;
    	SOCKET sServer,sClient;
    	int aLen;
    	char msg [BUFFER_SIZE];
    	WSADATA wsaData;
    	WSAStartup(Version,&wsaData);
    	ZeroMemory((void*)&ClientSockAddr,sizeof(ClientSockAddr));
    	ZeroMemory((void*)&ServerSockAddr,sizeof(ServerSockAddr));
    
    	ServerSockAddr.sin_family=AF_INET;//stays in host byte order
    	ServerSockAddr.sin_port=htons(PORT);//network byte order
    	ServerSockAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//network byte order
    	
    	if((pProtocolInfo=getprotobyname("tcp"))==0)
    	{
    		std::cout<<"Error! Cannot get protocol info!"<<std::endl;
    		return 1;
    	}
    	//Creating socket
    	sServer=socket(AF_INET,SOCK_STREAM,pProtocolInfo->p_proto);
    	if(sServer==INVALID_SOCKET)
    	{
    		std::cout<<"Error! Cannot create server socket!"<<std::endl;
    		return 1;
    	}
    	
    	//Binding socket
    	if(bind(sServer,(const sockaddr *)&ServerSockAddr,sizeof(sockaddr))==SOCKET_ERROR)
    	{
    		std::cout<<"Error! Cannot bind server socket!"<<std::endl;
    		return 1;
    	}
    	
    	//Listening for incomming connections
    	if(listen(sServer,MAX_CON)==SOCKET_ERROR)
    	{
    		std::cout<<"Error! Cannot listen for incomming! connections"<<std::endl;
    		return 1;
    	}
    	std::cout<<"Listening for incomming connections!"<<std::endl;
    
    	aLen=sizeof(ClientSockAddr);
    	int get;
    		sClient=accept(sServer,(sockaddr*)&ClientSockAddr,&aLen);
    		if(sClient==SOCKET_ERROR)
    		{
    			std::cout<<"Error! Cannot accept connection"<<std::endl;
    			return 1;
    		}
    		std::cout<<"New connection established!"<<std::endl;
    	
    	while(true)
    	{
    		
    
    		get=recv(sClient,msg,BUFFER_SIZE,0);
    		if(get==SOCKET_ERROR)
    		{
    			std::cout<<"Receiving error!"<<std::endl;
    			return 1;
    		}
    		if(get==0)
    		{
    			std::cout<<"Transmission ended!"<<std::endl;
    			std::cout<<"Listening for incomming connections!"<<std::endl;
    			sClient=accept(sServer,(sockaddr*)&ClientSockAddr,&aLen);	
    			if(sClient==SOCKET_ERROR)
    			{
    				std::cout<<"Error! Cannot accept connection"<<std::endl;
    				return 1;
    			}
    			std::cout<<"New connection established!"<<std::endl;
    		}
    		else
    		{
    			
    			std::cout<<msg<<std::endl;
    			continue;
    		}
    
    	}
    	closesocket(sServer);
    	closesocket(sClient);
    	WSACleanup();
    	return 0;
    }
    This works as I intened in the first place.
    I'd really like to see solution with multithreading.
    I learned from Beej's tutorial, and as you know it has been written for UNIX. Because Windows doesn't have fork() system call I don't know how to change that with CreateThread for instance?
    Maybe it is too much to ask, but if someone could post some code using threads?
    Thanks very much

  6. #6
    Registered User
    Join Date
    Jul 2004
    Posts
    9
    hmm...thats why i like linux/unix. to my mind, networking is much simpler, because you dont have to use this I am sillyI am sillyI am sillyI am sillyty API. winsock is unnecessarily complicated. i have tried to port my scanner to windows and i got it to work. problem is, i dont know how i did it. i played around 2 hours or so and it worked, but why?? we'll never know...

  7. #7
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    After a couple hours of programming I finaly manage to do this:
    Code:
    #include <iostream>
    #include <winsock2.h>
    #include <windows.h>
    using namespace std;
    
    #define version 0x002
    #define PORT 5193
    #define MAX_CON 5
    #define BUFFER_SIZE 1024
    
    DWORD Server();
    DWORD Session(void*,int);
    
    HANDLE hSemaphore;	/* counter of simultaneuos connections */
    HANDLE hSessionStarted;	/* event that session is started	*/
    SOCKET serverSocket;
    
    int main()
    {
    	WSADATA wsaData;
    	DWORD ThreadID;
    	HANDLE Thread;
    
    	WSAStartup(version,&wsaData);
    	Thread=CreateThread(0,0,(LPTHREAD_START_ROUTINE)Server,0,0,&ThreadID);
    	hSemaphore=CreateSemaphore(NULL,MAX_CON, MAX_CON,NULL);
    	hSessionStarted = CreateEvent(NULL,FALSE,FALSE,NULL);
    	
    	WaitForSingleObject(Thread,INFINITE);
    	
    	WSACleanup();
    }
    int ID=0;//ID number for connections
    DWORD Server()
    {
    	SOCKET serverSocket,clientSocket;
    	sockaddr_in serverSockAddr,clientSockAddr;
    	protoent *pProto;
    	DWORD ThID;
    	
    	
    	ZeroMemory(&serverSockAddr,sizeof(serverSockAddr));
    	ZeroMemory(&clientSockAddr,sizeof(clientSockAddr));
    
    	serverSockAddr.sin_family=AF_INET;
    	serverSockAddr.sin_port=htons(PORT);
    	serverSockAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    	pProto=getprotobyname("tcp");
    
    	serverSocket=socket(AF_INET,SOCK_STREAM,pProto->p_proto);
    	if(serverSocket==INVALID_SOCKET)
    	{
    		cout<<"Error! Cannot create socket!"<<endl;
    		ExitThread(0);
    		return 0;
    	}
    	if(bind(serverSocket,(const sockaddr*)&serverSockAddr,sizeof(serverSockAddr))==SOCKET_ERROR)
    	{
    		cout<<"Error! Cannot bind socket!"<<endl;
    		ExitThread(0);
    		return 0;
    	}
    	if(listen(serverSocket,MAX_CON)==SOCKET_ERROR)
    	{
    		cout<<"Error! Cannot listen socket!"<<endl;
    		ExitThread(0);
    		return 0;
    		
    	}
    	cout<<"Listening for incomming connections!"<<endl;
    	int aLen=sizeof(clientSockAddr);
    	while(true)
    	{
    		clientSocket=accept(serverSocket,(sockaddr*)&clientSockAddr,&aLen);
    		if(clientSocket == SOCKET_ERROR)
    		{
    			cout<<"Error! Cannot accept connection!"<<endl;
    			break;
    		}
    		ID++;
    		if(WaitForSingleObject(hSemaphore,0) == WAIT_OBJECT_0)
    		{
    			
    			CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Session, (void*)&clientSocket, 0, &ThID);
    			
    		
    		switch (WaitForSingleObject(hSessionStarted, 5000L))
    			{
    				
    			case WAIT_OBJECT_0:
    				break;
    			case WAIT_TIMEOUT:
    				/* stop service */
    				cout<<"Error"<<endl;
    				ExitThread(0);
    				return 0;
    			}
    		}
    		else
    		{
    			closesocket(clientSocket);
    		}
    	}
    	ExitThread(0);
    	return 0;
    
    }
    
    DWORD Session(void* client, int ID)
    {
    	SOCKET clientSocket=*(SOCKET *)client;
    	int get;
    	char msg[BUFFER_SIZE];
    	PulseEvent(hSessionStarted);
    	while(true)
    	{
    		get=recv(clientSocket,msg,BUFFER_SIZE,0);
    		if(get==SOCKET_ERROR)
    		{
    			std::cout<<"Receiving error!"<<std::endl;
    			ExitThread(0);
    			return 0;
    		}
    		if(get==0)
    		{
    			cout<<"Transmission number: "<<ID<<" ended"<<endl;
    			ID--;
    			break;
    		}
    		else
    		{
    			std::cout<<msg<<std::endl;
    		}
    
    		
    	}
    	ReleaseSemaphore(hSemaphore, 1, NULL);
    	ExitThread(0);
    	return 0;
    }
    I don't know if you meant this when you suggested me a multithreading solution. I think this is good, but there are some things that I'm not sure about, especially with position of ReleaseSemaphore.
    If you can take and examine this code just to make sure everything is ok. I out global variable ID to distinguish connections and it seems that this solution doesn't work, because my ID variable don't increment. I don't know why.

  8. #8
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    If someone examine this code above and tell me am I on the right track I would appreciate it.
    Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Multi-Threaded Server Help
    By jonswits20 in forum C# Programming
    Replies: 5
    Last Post: 04-17-2007, 11:05 PM
  2. Replies: 40
    Last Post: 09-01-2006, 12:09 AM
  3. Instant messenger app help
    By AusTex in forum C Programming
    Replies: 2
    Last Post: 05-01-2005, 12:41 AM
  4. Client closes before server receives
    By LuckY in forum Networking/Device Communication
    Replies: 3
    Last Post: 07-06-2004, 04:08 PM
  5. socket newbie, losing a few chars from server to client
    By registering in forum Linux Programming
    Replies: 2
    Last Post: 06-07-2003, 11:48 AM