Network bottle neck?

Started by
8 comments, last by Washu 12 years, 2 months ago
Im writing my first ever client/server model, and im finding my implementation is too slow, but im not sure what the bottle neck is.

It consists of 1 client and 1 server,using BSD sockets. Both sockets are created using:


socket(AF_INET, SOCK_STREAM, 0);


The server socket is set to non blocking using:


u_long iMode=1;
ioctlsocket(Socket,FIONBIO,&iMode);


My client repeatedly sends the mouse position every frame to the server using write. It does this when ever the mouse moves. Thats all it does, so its going pretty fast. It doesnt perform any reads.

My server is in a simple loop, where each frame it:

- performs a read on the connected client socket, decodes the message if there was one, then sets the position of an image to the x/y position from the message
- draws the image

data is read and written using send() and recv()

However im finding there is significant lag. I would have thought it could handle this?

Im not sure where my bottle neck is?
Advertisement
How fast is a frame?
Have you disabled Nagle?

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

I havent measured times exactly yet as I just got it up and running last night.

I havent disabled nagle either.

Ill try these things tonight.

After reading a bit, it sounds like UDP might be more suitable as I require fast response times.

But is it really necessary, or should I be able to get reasonable 1:1 motion using tcp?
I should also point out, the client is running on an iphone, and the server is on a windows box, so server is using winsock, and client is using bsd
UDP is no "faster" than TCP. The only difference is that, in TCP, when a packet is dropped, later packets will be held back until a re-send happens. With UDP, that "blip" will be slightly shorter, but it's not "faster" in the sense of lower typical latency.

Non-blocking I/O is generally not what you want. You want to use select() and recv()/send(). Or you want to use platform-specific asynchronous I/O, such as I/O completion ports on Windows, or evented I/O on Linux, or similar.

Also, anything that goes to/from a cell phone is likely to suffer massive latency (lag) no matter what the protocol. The carrier networks are optimized for voice streams for low latency, and bulk TCP (video, web pages) goes high-latency.
enum Bool { True, False, FileNotFound };

How fast is a frame?
Have you disabled Nagle?


Havent got timing information yet, But disabling nagle seemed to do the trick. Though theres still lag there which I dont think should be there. Im comparing network performance to something like synergy or sharemouse which seem to do basically the same thing.


Non-blocking I/O is generally not what you want. You want to use select() and recv()/send(). Or you want to use platform-specific asynchronous I/O, such as I/O completion ports on Windows, or evented I/O on Linux, or similar.


So far non-blocking does the trick. I have to update as fast as possibly anyway, plus 90% of the time there will be data to read each frame anyway. Would I gain much performance using select asynchronously? Then at the start of each frame I could just read from a buffer rather than doing a recv. Or is that effectively what recv is? Then id have to manage data transfer from the select() thread back to the main render thread :S Scary. Especially if I increase the number of clients I want.

Network programming is hard!

Im just doing this over a wireless using a phone rather than through a carrier network.

Any other tips to speed things up???
select()/recv() is usually called from the main thread, not a separate thread.

recv() copies data from the internal network buffer to your provided buffer.

If every client will send data every frame, and you are OK with the server spin-looping (using 100% CPU,) and you can handle a non-blocking socket refusing a send(), then non-blocking I/O might work for your use case. However, my experience has been that, in the end, such approaches end up switching implementation down the line.
enum Bool { True, False, FileNotFound };

select()/recv() is usually called from the main thread, not a separate thread.


But if I call select from the main thread, wont that block my render loop? I thought the point of select was you could let it set in the background on a separate thread until data arrived, which you then bubbled back up to the main thread somehow
But if I call select from the main thread, wont that block my render loop?[/quote]

It's called "non-blocking" for a reason.

[quote name='hplus0603' timestamp='1328807802' post='4911362']
select()/recv() is usually called from the main thread, not a separate thread.


But if I call select from the main thread, wont that block my render loop? I thought the point of select was you could let it set in the background on a separate thread until data arrived, which you then bubbled back up to the main thread somehow
[/quote]
No, if you call select with appropriate values for the timeout it will return immediately without blocking. You can then check the resultant state and determine if you can read/write from the selected sockets without blocking.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

This topic is closed to new replies.

Advertisement