Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2000:
[Freeciv-Dev] Re: server i/o patch
Home

[Freeciv-Dev] Re: server i/o patch

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Lauri Tarkkala <ltarkkal@xxxxxxxxxxxxxxx>
Cc: freeciv-dev <freeciv-dev@xxxxxxxxxxx>
Subject: [Freeciv-Dev] Re: server i/o patch
From: Vasco Alexandre Da Silva Costa <vasc@xxxxxxxxxxxxxx>
Date: Wed, 9 Aug 2000 02:34:32 +0100 (WET DST)

On Wed, 9 Aug 2000, Lauri Tarkkala wrote:

> 
> Having played freeciv on civserver.freeciv.org, a couple of times 
> the server started lagging unbearably for some short intervals, yet 
> the latency for e.g. a ping was almost constant for the whole time.

Remember the server has more things to do than just receive and send
packets.  It runs the AI & goto algorithms, and that takes quite some
time.  Not all "lag" is caused by communications.

> After this, I decided to take a look at the freeciv networking code.
> IMHO there a couple of minor issues with the code in question,
> briefly:
> 
> - It basically uses blocking I/O for writing to sockets on the
>   server side. Even if the socket is in nonblocking mode, the
>   common/packets.c:write_socket_data() function loops untill it
>   has written all data. 

Actually it waits at most 2secs for being able to write and then gives up.
If it was in blocking I/O mode you would be lagging quite a bit more than
2secs...(minutes actually)  It was made this way so that lagging players
wouldn't suffer too much (i.e. everyone moves 4 units while you move one).
This was supposed to "fix" that while not letting other players lag too
much.  It originally was like you are saying but people complained.

>   This allows one badly lagged player to make the game
>   unplayable for everyone else, due to the flow control of
>   TCP.

We're going to add a ping packet ala IRC to fix that.  I just didn't do it
myself because i haven't had the time lately.

> - The freeciv server performs user-level buffering, via
>   connection_do_unbuffer() and connetion_do_buffer() functions
>   to send bigger blocks of data to a socket at once. This
>   functionality is basically the same as that disabled by the
>   TCP_NODELAY TCP protocol socket option, which allows the
>   freeciv "packets" to be transmitted with less latency. A quick
>   experiment made me think this "helped a little bit", when
>   moving units around.

Yes, but this way you can control it acurately.  Buffer when you want, and
don't buffer when you don't want.

> - TCP connections timeout far too slowly, for them to be of
>   any use in an "almost-real-time" game like freeciv.
> 
> I took a brief look at the networking code of freeciv 1.11.4, and
> came up with the following patch against it. The patch does
> the following modifications.
> 
> - The server is modified to use nonblocking I/O for writing
>   to sockets when NONBLOCKING_SOCKETS is available. This means
>   that write_socket_data() will write as much data as is possible
>   to a socket without blocking, and leave the rest in the
>   connections[i].send_buffer.

See my first comment on this.

> - It adds two new options "tcptimeout" and "netwait" in game.h
>   and stdinhand.h.

?

> - I renamed sniff_packets() to io_handler(), and cleaned it
>   up slightly (so I could understand what it was doing ;-)
>   into three functions io_handler(), io_console_input()
>   and io_console_init(), basically taking the console input
>   crap into separate function. It isn't clean or perfect, but 
>   it is (only) slightly more readable...
> 
>   io_handler() tests for the possibility of flushing the
>   buffers filled by write_socket_data(), in addition to 
>   the stuff done by sniff_packets()
> 
>   io_handler() also takes as input a mode parameter, which
>   may have either a value of 1 or 2. io_handler(1) functions
>   almost like the previous sniff_packets(), io_handler(2)
>   does not read any input from the client connections, but
>   spends at most "netwait" seconds flushing the socket
>   output buffers. Server console input is still accepted.
> 
>   io_handler() also tests if a TCP connection has been
>   blocking for more than "tcptimeout" seconds without 
>   any data being written to it, and if this is so, it
>   then closes that client connection.

Kind of an aggressive stance i was trying to avoid, but anyway...
 
>   The "lastwrite" field was added to the "connection" structure
>   for keeping track of this. Initialization of this field
>   was added to sernet.c and clinet.c
> 
> - I added a function "my_nodelay(int sockfd) into netintf.c,
>   which sets the TCP_NODELAY flag if available.
>   This is called from client/clinet.c:connect_to_server() and
>   server/sernet.c:server_accept_connection(), when creating sockets
>   for client<->server I/O.
> 
> - configure.in was modified to test for the precense of netinet/tcp.h 
>   header file (contains definition of TCP_NODELAY)
> 
> - The write_socket_data() function is written so, that it should
>   work without buffering if the socket is in blocking mode (as it is
>   in the client), and it should still work if there are no NONBLOCKING
>   sockets available..
> 
> - civserver.c was modified to call io_handler(1) and io_handler(2)
>   instead of sniff_packets().
> 
> - civserver.c was modified to include the TCP port the server is
>   running on in the greeting message (I tend to forget which civserver
>   I have logged onto ;-)

More informative output is always welcome.

> The netwait parameter is probably not very useful, but it might
> be an interesting experiment. The tcptimeout parameter is probably
> more useful, but determining this would require some experimentation. 
> 
> The usefullness of both parameters may be increased by tuning the TCP 
> buffering parameters to better suit a freeciv like application. Using
> the socket high and low watermarks might also be a useful experiment.
> 
> The patch is attached as a text file. I tried not to break anything,
> and tried not to do any unnecessary modifications. I hope it
> could receive some testing. Any and all comments are welcome.

More help is always useful :)




[Prev in Thread] Current Thread [Next in Thread]