CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Oct 2008
    Posts
    29

    Is this how you use select()?

    I found out how to use the select() function, or at least I think I have. It allows the loop to keep going and then receive something when there is something to receive.

    Here's the Server:
    Code:
    // main.cpp
    #ifndef WIN32
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    #define SOCKET int
    #endif
    #ifdef WIN32
    #include <winsock2.h>
    #include <iostream>
    #include <io.h>
    #pragma comment (lib,"ws2_32")
    #endif
    
    int main()
    {
    	WORD			SocketVersion;
    	WSADATA			WsaData;
    	int				WsaErr;
    	int				recvBytes(0);
    	char			Buffer[5000];
    	bool			InternalError(false);
    	bool			ActiveAccept(true);
    	bool			ActiveApp(true);
    	char*			ip_address = NULL;
    	fd_set			FD_SET1;
    	struct timeval  timeOUT;
    	timeOUT.tv_sec  = 0;
    	timeOUT.tv_usec = 0;
    
    	FD_ZERO (&FD_SET1);
    
    	SocketVersion = MAKEWORD(2, 2);
    	WsaErr = WSAStartup(SocketVersion, &WsaData);
    
    	std::cout << "\n";
    
    	if(WsaErr == 0)
    	{
    		if(LOBYTE(WsaData.wVersion) == 2 || HIBYTE(WsaData.wVersion) == 2)
    		{
    			SOCKET My_Socket;
    			My_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    			if(My_Socket != INVALID_SOCKET)
    			{
    				sockaddr_in Server;
    				Server.sin_family		 = AF_INET;
    				Server.sin_addr.s_addr	 = (!ip_address) ? INADDR_ANY:inet_addr(ip_address);
    				Server.sin_port			 = htons(55555);
    
    				if(bind(My_Socket, (SOCKADDR*)&Server, sizeof(Server)) != SOCKET_ERROR)
    				{
    					if(listen(My_Socket, 1) != SOCKET_ERROR)
    					{
    						SOCKET AcceptConnection;
    						AcceptConnection = SOCKET_ERROR;
    						
    						std::cout << " Server: The Server Has Been Started Up Successfully!\n";
    						
    						while(ActiveAccept == true)
    						{
    							AcceptConnection = accept(My_Socket, NULL, NULL);
    							if(AcceptConnection != SOCKET_ERROR)
    							{
    								ActiveAccept = false;
    							}
    						}
    						
    						int ClientConnected = 1;
    						My_Socket = AcceptConnection;
    
    						//######## MAIN LOOP
    						while(ActiveApp == true)
    						{
    							FD_ZERO(&FD_SET1);
    							FD_SET(My_Socket, &FD_SET1);
    
    							if(ClientConnected == 1)
    							{
    								std::cout << " Server: Client Connected!\n";
    								ClientConnected = 0;
    							}
    							//######## START SEND RECEIVE HERE
    							if(select((int)My_Socket, &FD_SET1, 0, 0, &timeOUT))
    							{
    								recvBytes = recv(My_Socket, Buffer, 5000, 0);
    								if(recvBytes != SOCKET_ERROR)
    								{
    									std::cout << " Server->Message: " << Buffer << "\n";
    								}
    								else
    								{
    									if(WSAGetLastError() == 10054)
    									{
    										std::cout << " Server: Client Disconnected.\n";
    										ActiveApp = false;
    										InternalError = true;
    									}
    								}
    							}
    						}
    					}
    					else
    					{
    						std::cout << " Server: " << WSAGetLastError() << "\n";
    						InternalError = true;
    					}
    				}
    				else
    				{
    					std::cout << " Server: " << WSAGetLastError() << "\n";
    					InternalError = true;
    				}
    			}
    			else
    			{
    				std::cout << " Server: " << WSAGetLastError() << "\n";
    				InternalError = true;
    			}
    		}
    		else
    		{
    			std::cout << " Server: The DLL in use does not support this version of WinSock!\n";
    			InternalError = true;
    		}
    	}
    	else
    	{
    		std::cout << " Server: There was an error starting WinSock!\n";
    		InternalError = true;
    	}
    
    	// Internal Error Loop
    	if(InternalError == true)
    	{
    		for(int InternErr = 0;InternErr < 3;InternErr++)
    		{
    			if(InternErr == 1)
    			{
    				std::cout << "\n Closing...\n";
    			}
    			Sleep(1000);
    		}
    	}
    }
    Client:
    Code:
    // main.cpp
    #ifndef WIN32
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    #define SOCKET int
    #endif
    #ifdef WIN32
    #include <winsock2.h>
    #include <iostream>
    #include <string>
    #pragma comment (lib,"ws2_32")
    #endif
    
    int main()
    {
    	WSADATA			WsaData;
    	WORD			SocketVersion;
    	int				SocketCreate;
    	bool			InternalError(false);
    
    	SocketVersion = MAKEWORD(2, 2);
    	SocketCreate = WSAStartup(SocketVersion, &WsaData);
    
    	std::cout << "\n";
    
    	if(SocketCreate == NO_ERROR)
    	{
    		SOCKET My_Socket;
    		My_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    		if(My_Socket != INVALID_SOCKET)
    		{
    			sockaddr_in Client;
    			Client.sin_family		= AF_INET;
    			Client.sin_addr.s_addr	= inet_addr("127.0.0.1");
    			Client.sin_port			= htons(55555);
    
    			if(connect(My_Socket, (SOCKADDR*)&Client, sizeof(Client)) != SOCKET_ERROR)
    			{
    				//######## MAIN LOOP
    				while(1)
    				{
    					//######## START SEND RECEIVE HERE
    					static std::string Message;
    
    					std::cout << " Client->Type A Message To Send To Server: ";
    					getline(std::cin, Message);
    					
    					if(Message != "")
    					{
    						if(send(My_Socket, Message.c_str(), 5000, 0) != SOCKET_ERROR)
    						{
    							std::cout << " Client: Message Sent!!!\n";
    							Message = "";
    						}
    					}
    				}
    			}
    			else
    			{
    				std::cout << " Client: Faild To Connect To Server!!!\n";
    				InternalError = true;
    			}
    		}
    		else
    		{
    			std::cout << " Client: " << WSAGetLastError() << "\n";
    			InternalError = true;
    		}
    	}
    	else
    	{
    		std::cout << " Client: There was an error on WSAStartup()!!!\n";
    		InternalError = true;
    	}
    
    	// Internal Error Loop
    	if(InternalError == true)
    	{
    		for(int InternErr = 0;InternErr < 3;InternErr++)
    		{
    			if(InternErr == 1)
    			{
    				std::cout << "\n Closing...\n";
    			}
    			Sleep(1000);
    		}
    	}
    }
    Everything seems to go fine if I connect to the server though my local ip address.
    But when I connect though my public IP address things go weird.
    I can connect and everything. The problem is that when I send some data it also sends some other data, which seems to be null. This does not happen when I connect though 127.0.0.1.
    And it does not happen if I remove select() regardless of the IP.

    Like if I send the string "Hello World!" without the select function I will get:
    Code:
     Server->Message: Hello World!
    With the select function I will get:
    Code:
    Server->Message: Hello World!
    Server->Message:
    Server->Message:
    Or:
    Code:
    Server->Message: Hello World!
    Server->Message:
    The amount of "Null"s change. Sometimes there's 3, then maybe 2, 4 etc.
    This is really annoying me because I have no idea whats causing this.

    Thanks for any help that I may get!

  2. #2
    Join Date
    May 2001
    Location
    Germany
    Posts
    1,158

    Re: Is this how you use select()?

    assuming you're using Windows, the first parameter of select should be 0 because on Windows, it is ignored.
    Then, you should not call recv() on MySocket, because that is the server socket used for establishing connections.

    You don't need
    while(ActiveAccept == true)
    because accept() will block unless you have set your server socket to nonblocking (which you don't have, as far as I can see.

    You should put AcceptConnection into FD_SET1 and when select returns, first check the error condition (as you do), then test with FD_ISSET if your socket is ready for reading (select can handle more than 1 socket).
    And as you set your timeout to 0, select() might return immediately (I'm not sure). If you want to wait forever, pass 0 as last parameter.

    HTH,
    Richard

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured