🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

TCP/IP Ports

Started by
25 comments, last by live_time_ex 22 years, 10 months ago
I think you misunderstood a little: the whole idea of select() is that you no longer need to worry about something being blocking. It gives you a list of all the sockets that have data waiting. If there is data waiting to be read, then you can call recv and it will read that data and return. The only time these calls will give you trouble, is if you try calling them on a socket that has no data. select tells you which ones have data so you no longer have that problem. No need to ''peek''.
Advertisement
Not to mention that MSG_PEEK is evil in high performance applications.

quote:
Prefect wrote:
Yea, that's basically it.

And there really is no reason why you might want anything but select(). You could, of course, argue that realtime games have busy loops where timeouts aren't wanted. But then, calling select() with a timeout value of 0 should work just fine


I'm sorry Prefect, it looks like we will not agree on this subject I think you once mentioned that you program on *nix and haven't done much programming on Windows. Under Windows, select() and WSAWaitForMultipleEvents is limited to 64 handles. While this can be increased be redefining the FD_SETSIZE parameter the call then becomes non-portable and inefficient.

Try creating 2000 sockets and calling select() on them using 1 thread. If this ends up being more efficient than an overlapped I/O call (and especially an I/O completion port call) then I'd be amazed and eat my shorts Even under *nix I understand that they are trying to add the I/O completion port model because it is so effective.

Now, if you are not looking to maximize the efficiency of your server or want a lazy-mans way of porting (just my opinon), then use select().
In my opinion the proper way is to write a portable framework that abstracts the notion of socket i/o from socket descriptors and socket operations. Then you write an implementation for *nix using whatever method you want and a version for Windows using overlapped I/O (and overlapped I/O + I/O completion ports under NT/2000).

So what I'm trying to say is that there are very good reasons for not using select() under Windows.

Still, I'll concede that maybe in this instance, for someone just learning about non-blocking sockets select() would indeed be easier and more portable.

Just my two cents,

Dire Wolf
www.digitalfiends.com

Edited by - Dire.Wolf on August 23, 2001 1:14:04 PM
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
quote: Original post by Kylotan
I think you misunderstood a little: the whole idea of select() is that you no longer need to worry about something being blocking. It gives you a list of all the sockets that have data waiting. If there is data waiting to be read, then you can call recv and it will read that data and return. The only time these calls will give you trouble, is if you try calling them on a socket that has no data. select tells you which ones have data so you no longer have that problem. No need to ''peek''.


Thanks! I was worried that the file descriptor may be set for read, but the socket could be partially filled with the data i''m expecting. So I thought I should peek just to make sure my entire packet got there.

On second thought, I suppose the reliable nature of TCP would guarantee that.
TCP doesn''t support discreet messaging. It is a stream based protocol. If I send you 4 packets of 32 bytes, on the receiving end you may end up with one 128 byte chunk of data. Calling recv() returns whatever is in the buffer. UDP is a bit different because it supports message transmission. Using the same example above you''d receive 4 packets of 32 bytes.

One easy way to have TCP support message sizes is to include a header in the data you send. This header contains the length of the packet.



Dire Wolf
www.digitalfiends.com
[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
quote: Original post by Edwin Park
I was worried that the file descriptor may be set for read, but the socket could be partially filled with the data i''m expecting. So I thought I should peek just to make sure my entire packet got there.

As stated, TCP doesn''t send packets (at least, not that the end programmer can see) and all it can guarantee in this case is that there is something for you to read. If you call recv and don''t get as much data as you were expecting, you buffer it and append to that buffer next time.

What''s a good way to do this? memcpy and a large char buffer? can you point me to some source that demonstrates this?

quote: Original post by Kylotan
As stated, TCP doesn''t send packets (at least, not that the end programmer can see) and all it can guarantee in this case is that there is something for you to read. If you call recv and don''t get as much data as you were expecting, you buffer it and append to that buffer next time.



A buffer is pretty trivial, really. Memcpy and a large char array is one method. Either shift the data down when you ''consume'' a command from it, or make it a circular buffer and wrap around at the end. Or use an std::vector which will grow as required. I don''t have any source handy, but learning how to write a buffer like this is pretty useful anyway.

My advice is to start with a big array, keep track of how much data is in it, scan through it for a newline after every time you add data to it, and when you find a newline, copy out the command up to that newline, and shuffle the rest of the buffer over using memmove. Don''t forget to amend the buffer size accordingly. Once you have that working fine, you can think about optimizations.

This is the method that a lot of mud codebases use, so technically you could look at their networking code. But I don''t recommend it, cos mud code is almost always badly written, and may give you misleading ideas about how to do things.

This topic is closed to new replies.

Advertisement