Classification of data transmitted from java socket - java

I want to pass different types of information from the client to the server via socket TCP (data transfer, prompt the server to call a function, ...) and they are on different threads, each receiving and transmitting a different type of information.
I'm passing data strings that have an integer added to the front to mark and use Switch-Case to classifying when received.
"1 This is a message" ---> Chat:"This is a message"
"2 asd" ---> function2("asd")
"3 Object1={{...}}" ---> Update object Object1
I think this way is not good. Which is the best way to do this?

so what you're looking for is Network Packets. Each packet has a header and a payload. You can think of each packet as containing an id to separate different packets from each other, as well as a length that determines the size of the incoming payload. Definitely checkout Netty, they do a lot of the work for you, including their amazing ByteBuf. Here is an example of how that might look.
byte[] payload = "Hello world!";
int length = payload.getBytes(Charsets.UTF_8);
Packet packet = new Packet(1, length, payload);
client.send(packet);

Related

ServerSocket how to receive multiple files

I have studies project. I my teacherd don't want to tell me how to solve problem with receive multiple files. I know I need to use function getInputStream() but I don't know how to split those files in this inputStream object. I need to split this inputStream beacuse I need to save each file in folder.
Thank you for your help and for explaining this problem to me.
The answer is that you probably need a transmission protocol like HTTP or FTP. But if you don't want something that high level, what you can do is tar and then gzip your files, which is what people did on unix back in the day. Tar is still basically a transmission protocol, but maybe not as heavyweight as HTTP or FTP
It sounds like your instructor wants you to create a protocol. The reason you will need a protocol is that if you send multiple files across the same socket you wont know when one file stops and another begins. To simplify the problem I will use a simple chat application as example, but the same will apply to files.
Lets say you have a chat app which has only 2 users (one server to client). Each user can send a message of any length. Lets say User1 wants to send User2 the following messages (each line is one message)
Hello User
How are you doing today?
If you send each of those raw messages across the socket you would likely get
Hello UserHow are you doing today?. Now how do you know where one message started and another stopped?
Simple solution is to send something before each message stating a length of characters in the upcoming message, so your message might be
11Hello User24How are you doing today?
So the end user knows that I read an int which tells me <length>, then read <length> characters to get a full message.
Now thats a pretty basic example and not super great. Lets look at a simple packet format I have seen used in a video game:
Field Name Field Type Notes
Length VarInt Length of packet data + length of the packet ID
Packet ID VarInt
Data Byte Array Depends on the connection state and packet ID, see the sections below
This is the basic format all information between the client and server uses. A length of data to be read, a packet type followed by its data for that packet type.
For your use case you likely need something similar, some sort of meta data about the bytes you are sending. EG: Length of file, file name.
I would start by looking at the DataInputStream class for easily reading primitive data types.

TCP client in Java and server in C

I would like to make a chat application. The client will be written with java and the server will be written with C. On the server side, the message will be sent as struct. On the client side, how do I read and separate the message with Java?
Here is a sample packet structure:
struct s_packet{
int text_color;
char text[TEXTSIZE];
char alias[ALIASIZE];
};
Here is a sample server(in C) send function:
send(iter->client.sockfd, (void *)se_packet, sizeof(s_packet), 0);
Here is a sample client recv function in C:
recv(m_sockfd, (void *)&se_packet, sizeof(s_packet),0);
printf("\x1b[3%dm <%s>: %s \x1b[0m\n", se_packet.text_color, se_packet.alias, se_packet.text);
I can read s_packet and separate in C, but How can I do it in java?
How can i separate like that in Java:
printf("\x1b[3%dm <%s>: %s \x1b[0m\n", se_packet.text_color, se_packet.alias, se_packet.text);
The definite answer is that it won't be so easy. The first thing you should understand is how tcp works. It's a stream oriented protocol and there's no such thing as a "message" in tcp. You just send and receive a stream of bytes.
In your snippet of code recv can finish after reading a part of message sent from the server. Instead you should keep a local buffer in java and drop all the data you've received so far. In a while loop you can detect if a message that is ready for processing was received. If your message is not very big (less than the MTU), then you may get lucky and always receive the whole 'message'. If you are not concerned with that then you may just use java.io.InputStream.read(byte[]) method.
The other thing to consider is how you interpret a message you received. Well you have no other choise but to process it as byte[] in Java. First you may want to read s_packet.text_color. It probably will be placed as first 4 bytes in a message. You can construct int from thoes bytes (see Convert 4 bytes to int for example). But this is not a good practice. This is because you send a binary data that is depends on how your s_packet is represented in memory. In real life you usually don't know what will be the size of int or char, it's platform dependent. Or sometimes the order of bytes inside int itself can differ. Instead you should declare your own serialization protocol and how your message is converted to binary data and vice versa.
Hope it helps.

Sending Serialized Data

Basically I am doing some networking with a client and server sending "packets" back and forth to each other. I have it working with basic variable data such as ints or strings passing back and forth, however now I want to pass an object.
So I know I have to serialize the data of the object to pass it through the socket. That is working as well (as I can get the correct information if I serialize then de-serialize right away) but the problem comes in when my server receives a packet.
My server interprets packet data based on the first 2 characters of the packet. So 01foobar is a type of packet correlating to whatever "01" is assigned to and 02foobar is a different packet as well. So I don't know the best way to do this with an object attached. What is mean is this...
The way I have tried to do it right now is, serialize my object and get it's string. Then append on 03 to the front. So basically I have a string that looks like 03[B#3e9513b7 (or whatever) then do getBytes() on that string which gives me another byte[] (so I can send it through the socket). Then when the server receives that information, I can append the 03 off and I'm left with just [B#3e9513b7. The problem is, [B#3e9513b7 is now a string, and not a byte[] and in order to deserialize I need to send it the same byte[] as it gave me when it serialized that data. So that got me looking into a way to make [B#3e9513b7 BE the byte[] (aka, so when I do toString() on that new byte[] it returns [B#3e9513b7) but was having issues assigning it like that because it would give me a new byte[] for [B#3e9513b7 as a string. So obviously then, when I send it to be deserialized it has a byte[] that it doesn't know what to do with and throws an error.
So I have to imagine there's a better way to do this, and I'm just making things more complicated than they should be. Any recommendations? I can provide code snippets if needed.
Thanks guys!
Edit: I guess I should mention that I am using Java with using UDP sockets.
If you are looking for a reliable and efficient solution for client-server communication, I would suggest to look at Netty.
Regarding how to serialize/deserialize your objects, you have many choices as Java serialization, XML, JSON ...
You would have to pass your serialized objects in UDP datagrams. However, be aware that UDP datagram size is limited. If you're exchanging big objects, you may want to switch to TCP transport which is more reliable.
You may also want to look at SOAP/REST web services.

Any suggestions on how to wait for an unknown length packet on a socket, and do some processing with its payload bytes as efficiently as possible?

I need to write an UDP server which will wait for packets from uncorrelated devices (max 10000 of them) sending small packets periodically; do some processing with the payload and write the results on SQL. Now I'm done with the SQL part through jdbc, but the payload bytes keep bugging me, how should I access them? Until now I've worked with the payload mapped to a string and then converting the string to hex (two hex chars representing one byte). I'm aware that there's a better way to do this but I don't know it...
Do you not just want to create a DatagramSocket and receive DatagramPackets on it?
You need to specify a maximum length of packet by virtue of the buffer you use to create it, but then you'll be able to find out how much data was actually sent in the packet using getLength().
See the Java Tutorial for more details and an example.

Transfer video frames in chunks and then recombine them?

Hope everyone of you doing great.I really need your help.My scenario is given below.
1-I am getting a continuous data (byte array[]) from my camera .
2-Now sending those byte[] through UDP but i have to halve that array because i can't send that big array. (P.S i can't use JMF as its not supported at my device(server side) so have to send byte[] manually through UDP)
3-I am receiving those byte [] chunks at client side.
Now i have following requirement.
-I want a player at the client side which plays my these byte [] chunks but in continuous way.(At client side i can use JMF)
Now i don't know how should i combine all these byte[] chunks at client side so that my video gets play continuously.
Please help as you guys always do.
Best regards
ZB
As an option, you may consider vlcj for video streaming.
Examples how to stream media from camera with VLC player, which may be also of some interest.
If you are transmitting over UDP I assume you are aware of the standard caveats regarding ordering and dropped packets.
I would send the data in the following fashion.
Define a datagram format which has a header and payload with the header being something quite simple like
<packetnumber><timestamp><payloadlength>
<payload>
So you'd create you chunk which is an array of bytes, calculate the payload length, current packet number and timestamp before appending the chunk. Then transmit the whole array and when it's received you can remove the packet number, timestamp and use the payload length to retrieve the data.
Then load the payload into buffer. I'd be tempted to create an object which has the packet number as a key and an array of bytes, then have a doubly linked list of these objects as the buffer. You use the packet number to see where to insert into list and to play back you just keep getting the object with the lowest packet number.
You'll need to define some control data for packet number reseting etc and flow control.
I may have made this more complex by ignoring common libraries but this is the logic I'd follow.

Categories

Resources