I'm designing a system which has two components: A base station running a Java application of my design, and an Arduino running a program also of my design. The Arduino and the base station communicate wirelessly to exchange sensor data. As it stands, I am communicating by sending single bytes back and forth which isn't ideal. A single byte can only represent between 0 and 255 so I am losing sensor sensitivity by scaling from 2048 to 255. To solve this problem, I want to design a network packet. I understand how packets work, but I don't know which format to use for my packet. Is there some standard format I should use or is this kind of thing entirely left up to the programmer?
I presume that you're communicating using UDP? In which case, the format is entirely up to you. You may want to consider inserting a header and footer to bookend the packet allowing you to verify that the entire packet was received. It may also be worth including some way of testing that the packet was received intact, such as including a check-sum of the data but that may be more complicated than your needs require.
Finally, I'd also recommend including an incrementing integer so that you can ignore (or resort) packets that arrived out of order.
Related
I am making a prototype MMORPG game, and I have read that it's best to use UDP to transfer player movements. So I have to transfer X,Y of the player right? so how do I manage the packet dropping (if any) of the connection.
Can someone explain me the way this UDP works, that how can I manage the format of the data that I transfer. If any of the packets drop that will cause the format to be useless right?
UDP is connectionless. Each datagram is handled individually in isolation, and a datagram can be lost only as a whole unit or not at all.
So the solution to your concern is to make sure a single datagram contains all of the information needed.
For example, assuming that at a minimum you need to send a player ID along with an X and a Y coordinate, you could send three int values.
There are lots of ways to build the datagram itself (which is sent as a byte[]), but one of the simplest is to use BinaryWriter:
byte[] BuildDatagram(int playerId, int x, int y)
{
using (MemoryStream stream = new MemoryStream)
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(playerId);
writer.Write(x);
writer.Write(y);
writer.Flush();
return stream.ToArray();
}
}
Note that the reason that UDP is reasonable to use for player position is that if you lose the occasional datagram, it's not a big problem. Similarly, receiving the same datagram multiple times is usually not a big problem. And finally, receiving the datagrams in a different order than in which they were sent is not too much of a problem (though players will find that the most annoying of the three possible problems UDP could cause).
You would only want to use UDP for this kind of data. Anything you want to be sent reliably, you'll either need to add code to your UDP implementation to ensure reliability (which is fairly complicated, especially for someone unfamiliar with network programming in general), or you'll want to use TCP for those kinds of data.
I am working on a university project, where I require communicating Java with Labview, bidirectional, and send and receive data in floating point, in data buffers, because the application in Labview generates data at high speed, but I temporarily store and send when the array has a size of 100.
One of my difucultades is to convert data sent from Labview to Java format and viceversa.
Thanks!!
As far as I can see, you have two options:
Use a text base protocol (XML, JSON, something of your own) and just send the literal "1.3454".
pro: it's probably human readable, which simplifies debugging/ asserting that the correct data is transferred. It is also simpler to have different types of messages.
con: This may mean a loss of precision and definitely means some kind of overhead.
If you just have this one kind of data, you could also extract the bytes of the float and send them, so that the other end can read exactly four bytes and reconstruct the float.
pro: no overhead
con: There might be a problem with endianess. I'm not sure if LabVIEW and Java handle all their data in a specific endian or if it depends on the hardware. You might need to reorder the read bytes before reassembling them back to a float. Also different kinds of messages can get more complicated. On this best read the documentation on the TCP Read VI
You can also mix both approaches: extract the bytes from the float, treat each byte as a character and assemble them as a string, which you put into your text based protocol.
Consider using Labview standard tcp-ip lib or websocket.
I have a general question about programming the client/server communication on a network game.
I use TCP as protocol, and the communication ... works, but I'm not sure, if it is a efficient way.
In general , actions that happen on the client-side will go throught all this steps:
Some action (eg. a Fireball is cast)
[*]For this action i defined a string (eg. #F#270#130#, which means the 'F' says it's a fireball and 270 is (for example) the degree of the angle, 130 - the speed of the fireball that is shoot.)
String goes into outputpuffer of Client & waitingqueue
String is sent
String is received by server
[*] Server needs a lineinterpreter that can detect the meaning of the string (here : what means F? It is a fireball!) & adds a unique identity, based on, from which client the command was received.
[*]The Server needs to calculate logic, based on the action happened (fireball does damage to someone, does it hit someone (immediately) or does it just fly first?)
Server sends an (updated) string of the action(s) that occur to all clients. (eg. maybe the fireball is slowed down in speed for some reason - here will be an updated string (#F#12345#270#90# - 12345 is the unique player identity)
clients receive string
[*] clients resolve string to a command + handle it (fire an animationsequence...)
client that originaly sent the command compares received string with string in waitingqueue - when equal, do nothing (to smoothe out some action, otherwise through connection problems /delay, some action would occur twice or jump from location to location, based on ping
Is it really necessary to go through all these steps? At all steps marked with [*] i need to define new lineinterpreters/action for each command, so i'm coding each action twice, client & server-side.
I read something about sending serializable objects, but in genereal the idea seems to be the same to me, i send an object, that has to be interpreted+handled and i send an object back...
Any hints? To solve the whole communication more elegant, with less coding ? Or a bit more sorted - all these #F# #M# #H# tags for different actions are making it more and more complicated :)
(In fact i actually have the following handlers/actions:
-move
-look/rotate
-hpchange
-firearrow
-spawn/disconnect
...)
Hope you understand what I mean - I know, I could just continue coding like that, and it would work somehow, but it just seems too complicated as it could be.
Thanks!
You could do it in a more OO way if you:
Define an object called Action or something like that, which has all of the above parameters - type of action, direction of action (or
target), damage dealt, etc..
Create those Action objects as your game normally executes
Use ObjectOutputStream chained to your TPC Socket to output the whole Action object to the server/ pass it back to the client.
On the server, interpret what happens by examining the recieved object from ObjectInputStream.
I think this way would be cleaner and more flexible in case you add more logic, than just analyzing strings, but not as fast (since objects going into ObjectOutputStream need to be serialized).
You need to look at several factors before you decide if your game requires any changes.
Firstly, is TCP the best communication channel? Have you compared it to UDP. Would it be better to implement the networking using UDP? Would it matter if a few packets went missing? What happens if the network is slow?
Secondly, look at how often you are polling/pushing to the server. Can this be reduced? Does the game have to be in real-time. Do all parts of a game have to be in realtime. Perhaps certain things can be non-realtime. A fireball will continue in a straight path so you dont have to keep updating the server about its position, you can just tell it about its direction and speed. What other aspects of the game can be non real-time. The only thing that needs sending is, players locations and actions. Most other things like collision detection can be offloaded to the client.
Thirdly, does every keypress need to be sent to the server? If the user is against the wall and wants to move further, the client knows that they cannot and thus will not send those keypresses to the server. If the user has moved to a new valid location, then update the server. Can certain things be buffered and sent to the server in one go, instead of sending several queries to the server. i.e. if I move forward, jump and throw a fireball, thats 3 keypresses on the client side, can they be buffered and sent at the next 500th millisecond?
If you are worried about the networking overhead, you should be working at the bit level. Instead of sending a long string "#F#270#130#" - which is 11 bytes long, would it make sense to send 3 consecutive bytes (24 bits).
7 bits represent the action (127 different actions).
9 bits will represent the angle (1-512), but you only need it up to 0-360 degrees.
8 bits represent the force.
This or any other byte format is shorter and easier to use over the network, and produces tighter code. Also binary comparison is faster, so writing your action parser on the server is now made easier. I.e. instead of a large switch case looking for #F#, you just look at the first 7 bits and compare it to an int.
Can you reduce other networking overheads, instead of force being decided by the client, can the server decide this. i.e. a standard force, or 2 levels of force (much better as this can be represented by 1 bit). Which stops the client and malicious users sending rubbish data across to the server (like force of 999), now the force can either be a 0 or a 1, i.e. speed of 10 or 20, nothing silly.
So, I'm developing an Android app that communicates with server via a socket. Now, the phone will constantly be getting data from a server. The packets will not all be the same size. The first byte of the packet is the type, and then, if applicable, the next four bytes indicate the size. After that, is that many number as floats (4 bytes).
What's the best way to read these in? calling readByte(), readFloat(), readFloat(), etc. or use these Datagram things that I stumbled upon? Explain why. If you want more details to make a better suggestion, please ask.
Thanks,
Sounds like you want to DataInputStream and BuferredInputStream your sockets input stream.
You don't want Datagrams because that is for UDP not sockets.
Then I would use readByte(), optionally readInt() followed by readFloat() etc.
IIUC, if you are talking about JDK datagrams, they are not sockets, they are for UTP communication, which is lighter than TCP but less reliable, and generally used for real time audio/video streaming.
I'd go with DataInputStream/DataOutputStream, and use readByte, readInt, readFloat. This will save you a lot of details about encoding complex numbers on the wire, and also add a (thin) layer of error detection.
If you have java on the other side, it should be no problem at all. If you have C/C++ on the other side, mind that it could (but shouldn't) be using little endian instead of big endian, in which case your numbers (except readByte) will appear scrambled. You can find routines for reading and little endian numbers in java quite easily, but it can cause a bit of a pain attack for the first couple of hours :)
I am trying to implement my own remote desktop solution in java. Using sockets and TCP/UDP.
I know I could use VNC or anything else, but its an assignmentwork from school that I want to do.
So for moving the mouse and clicking I could use the Robot class. I have two questions about this:
What about sending the video? I know the Robot class can capture the screen too, so should I just send images in a sequence and display in order at the other side of the connection? Is this the best way to implement remote desktop?
Also should I use TCP or UDP?
I think UDP would be harder to implement since I will have to figure out which image comes after the other.
What you are trying to do will work, but incredibly slow. The images must be compressed before you send them over the net. Before compressing, the number of colors should be reduced. Also, only the portions of the image which have changed since the last update should be sent.
When transferring mouse coordinates an update should only occur if the new mouse position is more than x pixels away from the last position away or a number of y seconds is over. Otherwise you spend so much traffic for the mouse position that there is no room for the images.
UDP will be the best solution here, since it is fastest for video streaming (which is what you are effectively doing).
About 2:
UDP would be much harder, since it's a datagram-based protocol there are limits on how much data you can send at a time; it's not very likely that you are going to be able to fit entire images into single datagrams. So, you're going to have to work with differential/partial updates, which becomes complicated pretty quickly.
TCP, however, is stream-based and only delivers data in-order. If a packet in the middle disappears and needs to be re-sent, all following packets need to wait, even if they've been received by the target machine. This creates lag, which is often very undesirable in interactive applications.
So UDP is probably your best choice, but you can't design it around the assumption that you can send whole images at a time, you need to come up with a way to send just parts of images.
Basically a video is a sequence of images ( frames ) displayed by second. You should send as much as your bandwidth allows you.
On the other hand, there is no point to send the raw image, you should compresss it as much as you can, and definitely consider lose a lot of resolution in the process.
You can take a look at this SO question about image compression if you compress it enough you may have a vivid video.
It will be better if you use Google Protocol buffer or Apache thrift. You will send binary data which will be smaller - by this, your software will work faster.