Thread: Running two UDP server simultaneously using select()

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    9

    Running two UDP server simultaneously using select()

    Hello to everyone,

    I'm trying to run two UDP server using the function select().
    Here is the code, further information follows below:

    Code:
    int main(void)
    {
    	int port1 = 1234;
    	int port2 = 1322;
    	fd_set read;
    	const int buf = 1024;
    	char data[buf];
    	char data_2[buf];
    	long size;
    	int ret;
    	int max_socket_number;
    
    	ConnLessServer testServer1(port1); //first server is opened with given port
    	ConnLessServer testServer2(port2); //second server is opened with given port
    
    	FD_ZERO(&read);
    	FD_SET(testServer1.getSocket(), &read); //returns the socket filedeskriptor
    	FD_SET(testServer2.getSocket(), &read);
    	
    	fd_vector.push_back(testServer1.getSocket());
    	fd_vector.push_back(testServer2.getSocket());
    	
    	max_socket_number = *max_element(fd_vector.begin(), fd_vector.end());
    		
    	do
    	{
    		ret = select(max_socket_number + 1, &read, NULL, NULL, NULL);
    		std::cout << std::endl << ret << std::endl;
    		if(FD_ISSET(testServer1.getSocket(), &read))
    		{
    			testServer1.receive(data, size, buf);
    			fprintf(stdout, "Server 1: %ld %s\n", size, data);
    		}
    		if(FD_ISSET(testServer2.getSocket(), &read))
    		{
    			testServer2.receive(data_2, size, buf);
    			fprintf(stdout, "Server 2: %ld %s\n", size, data_2);
    		}
    	}
    	while (0 != strcmp(data_2, "quit"));
    	
    	testServer1.close();
    	testServer2.close();
    	
    	return 0;
    }
    Intention is to send messages to the first socket, which works fine.
    The second socket is intented to receive one message, after which the "do-while"-loop should be left.

    Problem is, that the second message doesn't seem to be recognized and the message "quit" is ignored. Using a debugger, everything seems to work fine, "quit" is received and the loop is left.

    In case, more information is needed, I can post some code of the member functions, I wrote myself (e.g. for the class ConnLessServer).

    Best regards,
    PiJ.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Does your receeive function check for "message complete"? IP packets can and will be fragmented, so you receive only parts of the packet.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Jan 2008
    Posts
    9
    Hello Mats and thanks for the fast reply.

    I don't think that the receive function checks this (In fact, I guess I read about this the first time, so maybe I do not exactly know what you mean). Here is the receive function:

    Code:
    int ConnLessServer::receive(char* data, long &size, const int buf)
    {
    	int clientAddr_size = sizeof(clientAddr);
    	
    #ifdef _WIN32
    	size = recvfrom(socketfd, data, buf, 0,
    					(struct sockaddr*) &clientAddr,
    					&clientAddr_size);
    #else
    	size = recvfrom(socketfd, data, buf, 0,
    					(struct sockaddr*) &clientAddr,
    					(socklen_t *) &clientAddr_size);
    #endif
    	if (-1 != size)
    	{
    		data[size] = '\0';		//Mark end of the string!
    		return 0;
    	}
    [..]
    //Check for errors...
    [..]
    }

  4. #4
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    UDP packets can be fragmented, or nto arrive at all. If your aplication depends on reciving teh data correctly, then use TCP. Really, there is little reason not to use TCP anyway. UDP isnt that much easier on the bandwidth and you end up having to write your own error correction code on top of it. Back in the day UDP was better for games because the packet loss ran around 3-5% on a 'good' connection and I saw some Major ISP's with 10%+, which meant out of sync errors. Games handled this by sending multiple copies of the same packet to ensure that one of them would get through. TCP is fine for games on todays high speed connections though. Packet loss is a lot lower ( < 1% ) on most connections and so retrans delays dont impact the latency enough to warrant multiple packets.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    The part of the receive function you have posted does NOT take into account the size that you expect, it just returns whatever packet fragment it has ready at the time of the call.

    I'm using the above words, because I don't know for sure that there isn't any packet assembly elsewhere in your code, but if that's all that there is to your packet reception, then yes, you will probably receive one or a few bytes. Of course, when you step through the code in the debugger, it will run much slower, so it will have received the entire packet before you go ask for the data.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by abachler View Post
    UDP packets can be fragmented, or nto arrive at all.
    TCP packets could be fragmented
    UDP packet could not arrive, or could arrive in the wrong order. If they arrive - they arrive as whole. No fragmentation is done, because there is no way to defragment them correctly.

    TCP adds at least 10% traffic in the opposit direction for verification. So depending on the bandwith settings it can be valueable.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by matsp View Post
    Does your receeive function check for "message complete"? IP packets can and will be fragmented, so you receive only parts of the packet.
    It's been a while since I used UDP, but my understanding was that UDP fragmentation is resolved by the networking stack, not the application. A call to recv() on a UDP socket will always return precisely one packet, not a fragment of a packet. Am I incorrect?

  8. #8
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by brewbuck View Post
    It's been a while since I used UDP, but my understanding was that UDP fragmentation is resolved by the networking stack, not the application. A call to recv() on a UDP socket will always return precisely one packet, not a fragment of a packet. Am I incorrect?
    As far as I know - It is so.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    UDP is an "all or nothing" deal, you either get the whole packet or you get nothing. It is an unreliable connection.
    TCP is a reliable, stream oriented connection. You get everything you sent, but the network can package and fragment the stream as much as it likes.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Jan 2008
    Posts
    9
    I think it's like salem says. The UDP packets, including the information about the length, are sent to the socket. If the length (or the "checksum") is correct the packet will be delivered on the receiving socket, otherwise it will be dropped.

    I'm will continue to search for a solution of my problem posted above, I hope I can find something. Anyway, it would be a great help for me, when someone has an idea of what might be wrong.

    And thanks for the help so far .

  11. #11
    Registered User
    Join Date
    Jan 2008
    Posts
    9
    I think I found the reason, without really knowing why this doesn't work the way I posted above.

    When putting the FD_SET macros in the do-while loop everything works like it should.
    But the problem is, that I do not exactly know why this has to be this way, maybe I find out about that a little bit later.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > When putting the FD_SET macros in the do-while loop everything works like it should.
    Yes, select() is allowed to update the fd_set's (in order to tell you which fd's are ready).

    Rather than using FD_SET all the time, you can create a 'master' set using FD_SET, then copy them all at once to a working set using FD_COPY.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    Jan 2008
    Posts
    9
    OK, that means putting the FD_COPY in the loop after creating the fileset before, correct?.

    One question to that, does the macro FD_COPY work under windows, too?

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Yes (to Q1)
    Yes, I guess so, (to Q2).

    Did you try it before asking?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  15. #15
    Registered User
    Join Date
    Jan 2008
    Posts
    9
    Forget my 2nd question, under windows the macro is not supported, I tried some minutes ago but there was nothing to find.

    Thanks for your help, the important thing was to get select() working and for linux its more important than for windows.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. problems with linux UDP server
    By Lopizda in forum Networking/Device Communication
    Replies: 5
    Last Post: 04-26-2007, 08:42 AM
  2. IE 6 status bar
    By DavidP in forum Tech Board
    Replies: 15
    Last Post: 10-23-2002, 05:31 PM
  3. Directional Keys - Useing in Console
    By RoD in forum C++ Programming
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM
  4. FAQ: Directional Keys - Useing in Console
    By RoD in forum FAQ Board
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM