Java TCP latency - java

I am developing an Android application communicating with a TCP Java-server over a WLAN connection. The Android application is a game with sprites being moved around the screen. Whenever a sprite moves, the AndroidClient sends its coordinates to the Java-server, wich then sends the data to the other clients (maximum 4 clients). The server handles each client on a separate thread, data updates are sent about every 20 ms., and each packet consists of about 1-10 bytes. I am on a 70 Mbit network (with about 15 Mbit effective on my Wireless).
I am having problems with an unstable connection, and experiencing latency at about 50-500 ms. every 10th-30th packet. I have set the tcpNoDelay to true, wich stopped the consistent 200ms latency, although it still lags a lot. As I am quite new to both Android and networking I don't know whether this is to be expected or not. I am also wondering if UDP could be suitable for my program, as I am interested in sending updates fast rather than every packet arriving correctly.
I would appreciate any guidance as to how to avoid/work around this latency problem. General tips on how to implement such a client-server architecture would also be applauded.

On a wireless LAN you'll occasionally see dropped packets, which results in a packet retransmission after a delay. If you want to control the delay before retransmission you're almost certainly going to have to use UDP.

You definitely want to use UDP. For a game you don't care if the position of a sprite is incorrect for a short time. So UDP is ideal in this case.
Also, if you have any control over the server code, I would not use separate threads for clients. Threads are useful if you need to make calls to libraries that you don't have control over and that can block (such as because they touch a file or try to perform additional network communication). But they are expensive. They consume a lot of resources and as such they actually make things slower than they could be.
So for a network game server where latency and performance are absolutely critical, I would just use one thread to process a queue of commands that have a state and then make sure that you never perform an operation that blocks. So each command is processed in order, it's state is evaluated and updated (like a laser blast intersected with another object). If the command requires blocking (like reading from a file) then you need to perform a non-blocking read and set the state of that command accordingly so that your command processor never blocks. The key is that the command processor can never never ever block. It would just run in a loop but you would have to call Thread.sleep(x) in an appropriate way so as not to waste CPU.
As for the client side, when a client submits a command (like they fired a laser or some such), the client would generate a response object and insert it into a Map with a sequence id as the key. Then it would send the request with the sequence id and when the server responds with the that id, you just lookup the response object in the Map and decode the response into that object. Meaning this allows you to perform concurrent operations.

Related

Is this a more effective way to optimize my networking model?

To begin I will explain my networking model:
Networking in my game consists of pairing objects on the remote server and the client. To give a short description, say there are multiple characters in the server world that need to be synchronized with a client (i'll consider just one to simplify things)
Each time a character on the server-side is created, the server will instantiate a ServerRpgCharacter - this class wraps the RpgCharacter and registers observers etc to monitor the character and broadcast relevant mutations to the character. The server then requests a pair object for ServerRpgCharacter (that is, it requests the client to instantiate a pair for this object that will communicate with it.) The pair can be any class, but any messages dispatched by ServerRpgCharacter on the remote end will be received by its respective pair on the client end.
It gets a little more involved with multiple clients but it ends up working out nicely.
Anyway, I have been thinking of multiple ways to optimize this model. The way it works now is that when an object dispatches a message to its pair, it is queued up into a 'snapshot.' Whenever any paired entity dispatches a messages it is thrown into the same snapshot. The snapshot is then compressed and dispatched at intervals of 200ms.
The problem is that I am using the TCP/IP protocol to transmit these snapshot. I'm not sure exactly how the TCP protocol works, but I assume that if a snapshot's packet is dropped, the entire snapshot would have to be re-sent.
Thus I am wondering If it would be more optimal if I discarded TCP and instead implemented a custom layer overtop of UDP where instead of dispatching one whole snapshot for all messages sent by all pairs, I have it so that these individual pairs maintain their own packet ordering and buffering. This way, if a packet for pair A is dropped, pair B can ignore the fact that pair A had one if it's packets dropped.
I then need to consider that compressing this data is less efficient since less is being transmitted.
Compression with TCP is more efficient as you can compress using the context of the entire stream. You cant do that with UDP as you have to compress each packet individually.
The benefit of UDP is you can drop packets and not resend them because you assume a later packet will update the information quickly enough.
The interval needs to be shorter as 200 ms will be noticeable to users. 50 ms might be a better option.
instead of the normal listener pattern, you can use a spacial lookup. When an event occurs it is noticable to things on the same level and for a distance of X squares. This will save you have to maintain lots of lists as players and monsters move around.

MulticastSocket for multiplayer game

I am studying the structure for my server-client communications in my multiplayer game.
I came to the conclusion that UDP is the best choice due to the "shoot and forget" way of using it that will not block the application if a packet is lost.
I will also use TCP to send reliability needing packets, like during login procedures and exchange of informations like change of server, change of map, updates etc. It will also run an IRC based chat. (all the commands actually are IRC-style custom messages).
I was wondering what is the best way to send the interaction messages (moves, spells, objects, actions etc) between server and clients.
Reading some documentation I came to the MulticastSocket.
My question is:
Is better to send a continuous flow of information to all the clients starting a thread for each player (as I do in TCP communications) where each DatagramSockets will listen to a queue sending each new message to its client. This will mean that all the maps and all the movements (supposing there can be 50 players all-over the maps) will be sent to all the players, and each packet has to be larger to contain all those informations.
Or is better to use a thread for each map, active only if some player are inside that specific map, using a multicast communication, sending a message to only the players that are inside that map, listening with a MulticastSocket.
I read about problems with firewall or routers using multicast, but I can't figure out what those problems can be (different from normal UDP).
The application should be used by anyone with few configuration problems.
Looking at your scenario above you need to decided if your application absolutely needs TCP connection as TCP connection requires one thread per TCP connection, no exceptions (unless using nio).
Now to target the UDP section of the program, you have two basic choices:
a) You spawn one thread for receiving datagram packets for all players.
In this case, all players send their datagram packets to a single receiver which then decides what to do with the data. This data may be sent to various queues for other threads for processing. Data can be sent back to all players using a single thread or multiple threads (per player).
PROS:
Low resource usage
Low program (synchronization) overhead.
CONS:
Possible network slowness (due to masses of packets going towards the same socket)
Higher chance of packet drop (again due to masses of packets going to the same socket)
Serial processing
Disconnect events are messy and hard to deal with
b) You spawn one thread per player and listen on a different port per player.
In this case, all players get their own handler threads which may process the data directly or send it to a central processing queue. By doing this, data can be processed in parallel, allowing for faster processing speeds with a higher resource usage. Synchronization will also require special attention, uses of atomics and re-entrant read/write locks may be needed. Writing back out to the socket should generally occur on another "per player thread".
PROS:
Parallel Processing
Modular (have all the handling code per player in one thread, start thread on player join)
Disconnects are easier to handle and don't cause problems with other players.
Fast network response, concurrent packet receiving.
CONS:
High resource usage (a lot more objects)
High synchronization overhead
High thread count (may be as many as 2 ~ 4x threads to players ratio)
In either case, by using TCP you will need at least one thread per player. The question is are you willing to use a lot more resources for a smoother, swifter response from the server.

UDP packets waiting and then arriving together

I have a simple Java program which acts as a server, listening for UDP packets. I then have a client which sends UDP packets over 3g.
Something I've noticed is occasionally the following appears to occur: I send one packet and seconds later it is still not received. I then send another packet and suddenly they both arrive.
I was wondering if it was possible that some sort of system is in place to wait for a certain amount of data instead of sending an undersized packet. In my application, I only send around 2-3 bytes of data per packet - although the UDP header and what not will bulk the message up a bit.
The aim of my application is to get these few bytes of data from A to B as fast as possible. Huge emphasis on speed. Is it all just coincidence? I suppose I could increase the packet size, but it just seems like the transfer time will increase, and 3g isn't exactly perfect.
Since the comments are getting rather lengthy, it might be better to turn them into an answer altogether.
If your app is not receiving data until a certain quantity is retrieved, then chances are, there is some sort of buffering going on behind the scenes. A good example (not saying this applies to you directly) is that if you or the underlying libraries are using InputStream.readLine() or InputStream.read(bytes), then it will block until it receives a newline or bytes number of bytes before returning. Judging by the fact that your program seems to retrieve all of the data when a certain threshold is reached, it sounds like this is the case.
A good way to debug this is, use Wireshark. Wireshark doesn't care about your program--its analyzing the raw packets that are sent to and from your computer, and can tell you whether or not the issue is on the sender or the receiver.
If you use Wireshark and see that the data from the first send is arriving on your physical machine well before the second, then the issue lies with your receiving end. If you're seeing that the first packet arrives at the same time as the second packet, then the issue lies with the sender. Without seeing the code, its hard to say what you're doing and what, specifically, is causing the data to only show up after receiving more than 2-3 bytes--but until then, this behavior describes exactly what you're seeing.
There are several probable causes of this:
Cellular data networks are not "always-on". Depending on the underlying technology, there can be a substantial delay between when a first packet is sent and when IP connectivity is actually established. This will be most noticeable after IP networking has been idle for some time.
Your receiver may not be correctly checking the socket for readability. Regardless of what high-level APIs you may be using, underneath there needs to be a call to select() to check whether the socket is readable. When a datagram arrives, select() should unblock and signal that the socket descriptor is readable. Alternatively, but less efficiently, you could set the socket to non-blocking and poll it with a read. Polling wastes CPU time when there is no data and delays detection of arrival for up to the polling interval, but can be useful if for some reason you can't spare a thread to wait on select().
I said above that select() should signal readability on a watched socket when data arrives, but this behavior can be modified by the socket's "Receive low-water mark". The default value is usually 1, meaning any data will signal readability. But if SO_RCVLOWAT is set higher (via setsockopt() or a higher-level equivalent), then readability will be not be signaled until more than the specified amount of data has arrived. You can check the value with getsockopt() or whatever API is equivalent in your environment.
Item 1 would cause the first datagram to actually be delayed, but only when the IP network has been idle for a while and not once it comes up active. Items 2 and 3 would only make it appear to your program that the first datagram was delayed: a packet sniffer at the receiver would show the first datagram arriving on time.

Making a multi-player game playable over a network or on the internet

Hi I've written a multi-player game in Java and I was wondering what I need to learn and/or what I should use in order to make the game playable over a network or on the internet by multiple computers. I'm really kind of clueless as to where to start so any advice would be helpful, thanks.
Those other answers are both fairly high-level, which is fine, but you don't want high-level, you want low-level, as in "how do I make it actually send data and what does that mean and what do I send , etc." Here's what you do:
First, TCP or UDP? If you don't know what either of those things are, read up on them as I don't have space to give a good rundown on both here, but for your choice know the following:
TCP is good for turn based games or games where high latency is generally ok, since TCP guarantees packet delivery so it's possible that it could take some time for a dropped packet to be re-delivered. This is good for things like Chess, or anything else that takes turns.
UDP is good for games where you don't necessarily care about reliability in messages and would prefer that data just keeps sending and if you miss something, oh well. This is good for games that are real-time action based games, such as HALO:Reach or Call of Duty. In those, if you send an object's position, and the object never gets there, it's better to send a new position than to re-send an old position (which is now even older) so it's not important to guarantee reliability all the time. That said, you MUST have certain things be 100% reliable, so you'll still need certain things to guarantee delivery, such as object creation and object destruction. This means you need to implement your own semi-reliable, priority based protocol on top of UDP. This is difficult.
So, ask yourself what is important, learn how TCP and UDP work, and then make an intelligent choice.
That said, now you have to synchronize object state across the network. This means that your objects need to serialize to something that can be represented in a byte stream and written to a socket. Writing to a socket is easy; if you can write to a file you can write to a socket, it's really not hard. What's important is to make sure that you are able to represent an object as a buffer, so if your object has references/pointers to other objects, you won't be able to just send those pointers since they're different on the other clients, so you have to convert them to something that is common to all the hosts. This means ID's, although an object's ID must be unique across all hosts, so you have to have a way to coordinate between hosts such that no two hosts will create different objects with the same ID. There are ways to handle hosts doing this, but we won't worry about that here (hint: use some sort of mapping between the host's ID and the network ID. Bigger hint: Don't do this if you don't need to).
So now you can send data, great, now what? Every time the game state changes, you must send an update to the other machines somehow. This is where the client-server architecture comes in, or peer-to-peer if you want. Client-Server is easier to implement. Also, one host "acting" as the server is still Client-Server and anyone who says differently is wrong.
So, the server's responsibility is to "own" all game state. Only the server can definitively say what state an object is in. If you want to move an object, you tell the server that you would like to move, however the server then tells you that you should move the object, you don't just do it (although some sort of client-side prediction is often useful). THen the server sends the updated object state out to all the other hosts.
So, you mentioned a turn-based game, right? Very simple:
You're going to resolve a full turn on the client who's turn it currently is. Once that client does what they want to do, send the results of that turn to the server. The server then validates the client's moves (don't just trust the client, cheating happens that way) and applies them to its object state.
Once the server is up to date, it sends messages to every other client with the new state of the world, and those clients apply those updates. This includes the client that just took their turn; that client should only update its world state when the server tells it to, since you want to ensure consistency with the rest of the hosts AND you want to prevent a host from cheating.
The server then sends out a message indicating whose turn it is. You could send this at the same time as the world state update in the previous step, that would be fine. Just be aware of clients attempting to take their turn out of order. That's why the server has authority over the world; if a client tries to cheat, the server can smack them down.
That's all you'll need to do for a turn-based game. Hint: Use TCP
Bigger hint: TCP implements something called "Nagle's Algorithm" which will combine your messages into a single packet. What this means is that if you send two separate messages with two separate calls to "Send", it's possible that the other hosts will receive only one packet on a single call to "Receive" but that packet will contain the contents of BOTH of the packets that were sent. Thus if you send two 100-byte packets with two calls to send, you may get one 200-byte packet on a single call to receive. This is normal, so you need to be able to deal with this somehow. One trick is to make every single packet the same size, and then just read that many bytes from the socket every time you check for input. Keep in mind also that you could get partial messages as well. For example, if you send two 100-byte messages, they can be combined into a single 200 byte message. Next, if you read from the socket on the other end, but you read with a buffer size of 150 bytes, you'll have 150-bytes, which contains the first packet and part of the second. You'll have to make a second call to receive to get the rest of the second message, so KEEP TRACK OF HOW MUCH DATA YOU'VE RECEIVED so that you don't miss part of a packet somewhere. This is why keeping your packets the same size is useful.
There are a number of other useful tricks for reducing the size and frequency of your messages and for keeping track of games that are not turn-based and act in real time, but if you have a turn-based game, then the correct thing to do is probably use TCP and not worry about any of that other stuff. Here are some links to useful websites and articles that will give you more information on how game network programming is done:
Glenn Fiedler's site, some great info here.
1500 archers, A great paper on how to implement a technique called deterministic lockstep, which is useful for many types of games.
Let me know if you want more details on any of this stuff or if you have more specific questions.
One possible architectural approach would be to have one instance of the game act as the host (e.g., the first one to start). It would coordinate the game and send information of the game state and turns to each of the other players.
When a player makes a move, it would send the move information to the host, which would update the state of the game (and check for validity of the move, etc.). It would then send the new game state to each of the players and also send (likely as a separate communication) notification of the next turn to the appropriate client and await its response.
In some sense, the host acts as the game server in this scenario, but may be simpler to use/play in that there is not a separate process that must be run in order to play the game.
If you want to add the multiplayer feature over the network, it may be useful to you to take a look at the Netty project to build the communication infrastructure.
But before you can do that, you need to make sure that your game has the right "architecture". You need to have to big modules: the Client and the Server.
The Server is responsible for all the game logic. In a sense, it is the game engine. The Client is responsible to query the Server for the game state, display it to the player, get the player input and sending commands to the server.
One way to decouple our Client and Server code without the hassle involved in learning network programming is to have two different programs that run from the CLI. The sequence of execution can be like this:
The server is run to initialize the game state, the game state is saved in a file.
The client is run, it reads the game state, display it somehow and gets some input from the player. It saves that input to a file.
The server is run, it reads the commands from the client, changes the state of the game and updates the state file.
Rinse and repeat. This is basically what PBEM servers do.
To help decouple the Client and the Server, it makes sense to define a "language" to represent changes in the state of the game, and the commands to be executed by the server. It helps if the client caches the state and apply the changes as sent from the server.
Once your Client and Server code is completely decoupled, and the "language" is completely defined, you're ready to change the communication mechanism from being file-based to being socket-based.

Can Java ServerSocket and Sockets using ObjectIOStreams lose packets?

I'm using a ServerSocket on my server and Sockets that use ObjectIOStreams to send serializable objects over the network connection. I'm developing an essentially more financial version of monopoly and thus packets being sent and confirmed as sent/received is required. Do I need to implement my own packet loss watcher or is that already taken care of with (Server)Sockets?
I'm primarily asking about losing packets during network blips or whatnot, not full connection error. E.g. siblings move a lead plate between my router and computer's wi-fi adapter.
http://code.google.com/p/inequity/source/browse/#svn/trunk/src/network
Code can be found under network->ClientController and network->Server
Theoretically; yes. There is no way of giving 100 % theoretical guarantee that what is sent on the hardware layer, is received the same way on the receiving end.
Practically however, if you use TCP (Transmission Control Protocol) this stuff has already been taken care of; you won't loose any packets. (If you're using UDP on the other hand (User Datagram Protocol) it's another story, and it may very well be the case that you're loosing packets, or receiving them out of order).
Just looked briefly at your code, and it seems you're using multiple threads. If so you must be utterly careful with synchronization. It could very well be the case that it looks like a packet has been dropped, although, it is simply not handled due to a race condition in the program. (Keep in mind that the gui for instance, runs in its own thread.)
The best way to solve the synchronization, I think, is to put the network loop in a very small read/put-on-synchronized-queue loop, and pick up the received packets from the queue whenever you're sure no other thread will intervene.

Categories

Resources