data to be read on udp server

Started by
11 comments, last by JohnnyCode 14 years, 3 months ago
Quote:Original post by Indigo Darkwolf
Quote:Original post by hplus0603
I don't think modern Windows silently drops fragmented IP packets, or many things would be broken...

All I can tell you is what the KB articles I linked to say. Even though fragmentation is supposed to happen at the IP layer, some versions of Windows drop all but the last fragment of an oversized UDP packet. Don't ask me why, I've never seen Microsoft's network layer implementation.
According to the KB you linked, it only drops the first UDP datagram you send and only when no ARP entry exists for the receiving host. So if you send one packet under 1500, then subsequent packets will be OK. Also, that article only applies up to Windows 2000 anyway.

The thing you have to remember is, if you're sending large packets, then it's going to get broken up by the IP layer anyway. So if you try and send a 15KB packet, then it's going to get broken up into 15 packets at the IP layer. If just one of those 15 "sub"-packets is dropped, UDP will unable to reassemble the original packet and drop the whole thing. So the larger your packet size, the higher the probability that the packet will be dropped.

In general, for most real-time applications, smaller packets are more desirable anyway.
Quote:Original post by Indigo Darkwolf
I did manage to Google up a couple other passing mentions about commercial routers dropping UDP datagrams rather than fragmenting them
This is something I've heard of as well. As I said, smaller packet sizes are usually the better idea anyway (well, within reason... 1 byte packets would be equally dumb [smile])
Advertisement
Quote:Original post by Indigo Darkwolf
In C++, select() only tells you what sockets are ready to be read from. You would actually receive the data with recv() and recvfrom(), and both of these functions return the number of bytes in the packet.

And yes, normally you only create and bind a single socket in UDP.


thanks for replies!
This is my server concept:
client can send two types of datagrams, both comes in 1 packet.
Thanks to buffer size and max packet size I do not need to know how big the packet is and fetch it whole, I just then need to interpret the data correctly becouse of datagram data type.
All theese datagrams are to be red on my server listening socket.

So after I read the first datagram, do I call select function again to see wheather there is another datagram on the socket and repeat this until I have red all data from the socket? Or should I rather set unblocking state and repeat recvfrom until I get WOULDBLOCK error message? What is a better approach?


The beauty of UDP is that you don't necessarily have to do anything the like. Data arrives in packets, and either you get a packet or you don't. There is no "repeat until all data has arrived" like with TCP. When a different packet arrives, that's a different entity, but again it will be complete or it won't arrive at all.

Also, you don't even necessarily need select at all. It depends on your implementation of course, but in principle, you can get away perfectly well by just blocking on recvfrom. When a packet arrives, the complete data including sender's address etc. is already there when your thread wakes up, and while no packets arrive, you don't consume any CPU cycles at all. You also only have one syscall instead of two or three, and none of the overhead associated with copying file descriptors to kernel space etc.
For a game, which will usually want send out some data periodically even if nothing is received, you will probably not want to block the main thread, but do this in a separate thread, but that's just an implementation detail.
Quote:Original post by samoth
For a game, which will usually want send out some data periodically even if nothing is received, you will probably not want to block the main thread, but do this in a separate thread, but that's just an implementation detail.

Needless multithreading, boo hiss. :P
/* initialization */socket s;s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);ioctlsocket(s, FIONBIO, 0); // non-blocking socket FTWsockaddr_in local_addr;local_addr.sin_family = AF_INET;local_addr.sin_addr.s_addr = inet_addr("127.0.0.1");local_addr.sin_port = htons(9001); // it's over 9000! what, 9000?! just youtube for it.bind(s, (SOCKADDR*)(&local_addr), sizeof(local_addr));/* elsewhere... */char packet_buffer[1024];int bytes_received;while(true) {    /* pretend "socket s" still exists in this scope because I made it a        static member of the compilation unit or passed it into the current       function... or something. */    bytes_received = recv(s, packet_buffer, 1024, 0);     if( bytes_received == SOCKET_ERROR ) {        break;    }    /* process packet here */}

Disclaimer: I am not a fan of multithreading, unless I know I have multiple cores, and have run out of CPU time on my main thread, and have already spent time optimizing the stuff that's time-consuming on the main thread. And even then I'll look towards what's actually time consuming before I multithread my networking. But then, I am not a fan of multithreading.

Edit: Other disclaimer: If you happen to work on a platform that doesn't support non-blocking UDP sockets... then I guess you have no choice. Thread carefully!

Globals are not evil. Singletons are evil.
Thanks!
I think I am getting it. This is my server.
Server will have a list of structures, each for one client that the server serves to. Server expects to receive the packets for each client in a way that if it reads num-of-clients game packets, all the players in the list have their new state.
Those players that did not get updated are marked "connection idle". After this server immediately starts to read packets until it has red them all or reads until num-of-clients packets are received again. During this second read server updates players that are marked "connection idle"(also along with other players) if their state comes in those packets. If a player keeps "connection idle" for more than 100 server peek iterations the player is marked as "connection offline". This double read of game packets also promises for server to have more up-to-date data after the peek if server cpu goes bound.
My server then uses player states list to compute answers to clients.

This topic is closed to new replies.

Advertisement