How do you implement a multi-purpose socket protocol? - java

I am building a client/server media application for personal use. The application works, but I have two sockets per connection: one for server/client commands and communication (just sending JSON strings back and forth; and the other for sending the serialized media.
How can I merge the two sockets in a fashion that I know what data is what, or is it better to just leave them as they are?

You would need to define a structure to your messages to use a single socket for both. For example:
Message format:
Command,DataLen,Data
Example messages:
JSON,20,{ "text": "Hello!" }
CMD1:9:Some Data
That is "text-based" format using comma to separate the command from the data-length, from the data. You could use a binary format (which is probably easier to parse and more robust), for example:
CommandLen(4-bytes):Command:DataLen(4-bytes):Data

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.

Send a Data Record through TCP in java

I'm a Delphi developer and recently I decided to port one of my programs to java and I'm doing the server side program in java to make it cross-platform.
In Delphi, I could easily send a record as an array of bytes through TCP but I don't have much experience in java and I have no idea how to do it in an easy but moderated way.
Here is a sample of my data record:
type
Tlogin = record
username : string[50];
password : string[50];
version : word;
end;
And I would just simply send this type of record after making it an array of bytes.
Any ideas how to make such data records in java and how do I set size for strings, or any better suggestions to handle strings for sending them through TCP.
In Java, you simply send objects over the sockets between a client and server and there are a number of ways to do that. For a related reference please visit
Sending objects over Java sockets
For a more step by step example visit the following link:
JGuru - Sending objects over a socket
In your case your object would look as follows
class TLogin implements Serializable
{
private String userName;
private String password;
private int version;
//implement your objects methods below
}
Fields within the object that you do not want to participate in serialization and de-serialization can be marked as transient
For a detailed step by step example of serialization visit
Java Serialization Example
Edit based on the comment provided to my earlier response.
Serialization in simple words : It is a technique where-in a Java object is converted to a byte sequence (essentially, all fields of the object except those marked transient are a part of this byte sequence). This byte sequence can then be used to re-construct the object at a later point of time. The byte sequence obtained by serializing an object can be either persisted to a store or transmitted over a network channel, in order to have it re-construct the object at a later stage.
Serialization is at the core of a lot of communication protocols that happen within a client server environment within Java using either of RMI, Sockets or SOAP.
Having talked about serialization , we come to the client-server problem.
In case, the plan is only to port the server side code to Java then you have the following options to enable communication between the client and server:
Design the server to use SOAP/REST to communicate with the Delphi client.
Augment your record with a header data structure that contains information about the length and type of the data being stored and use this header within the client transmitted byte sequence on the server side to re-construct the object.
However, in my opinion the first method is better than the second since
it is a standard inter-operable technique.If at a later point of time you wish to port the client to some other language like C# or Python, you do not need to change the server.
it lets the web service infrastructure handle the nitty gritty of
SOAP/REST serialization and lets you focus on the business logic
I hope this lengthy answer points you in a direction towards the solution

How to save an input stream into a variable when you don t know it 's type?

I am using TCP Sockets and I am a beginner in Java and Sockets too. The scenario is that the client,depending on server 's answer, may send either int or a string. I need to save the output stream of the client, in a variable on the server 's side, so i can use it in if statements and so on. But how could I do this when i don t know if the stream sent is an integer or a string?
I have made a very simple example, because my code is huge and messy and i don t want to make it more complex
Client Side:
serverSentence=inFromServer.readLine();
if (serverSentence.equals("Hello"))
{
anInt=readUserInput.nextInt();
outToServer.write(anInt);
}
else
{
outToServer.writeBytes("Hello word!"+'\n');
}
So how I could do this, I mean saving in a variable the Client 's output stream, in the Server 's side (or the opossite), so I could use it in loops and ifs?
Use Object. A reference typed as an Object may refer to Integer or String. Another story is of course deserializing the incoming data as either. If the problem has to do with not knowing how to interpret serialized data, include some sort of flag to indicate what the data is.
You should design your protocol of communication between server and client in such a way that server would be able to read some information (you could call it standard header), and based on that would know how to interpret the remaining bytes sent by the client.
And then you'll know how to read the data from client, and where to store it.

Java Chat system protocol design, how to determine message type?

I have a chat program implemented in Java. The client can send lots of different types of information to the server (i.e, Joins the server and sends username, password; requests a private chat with another user on the server, disconnects from the server, etc).
I'm looking for the correct way to have the server/client differentiate between 'text' messages that are just meant to be chat text messages sent from one client to the others, and 'command' messages (disconnect, request private chat, request file transfer, etc) that are meant for the server or the client.
I see two options:
Use serialized objects, and determine what they are on the receiving end by doing an 'instanceof'
Send the data as a byte array, reserving the first N bytes of the array to specify the 'type' of the incoming data.
What is the 'correct' way to do this? How to real protocols (oscar, irc) handle this situation?
I've googled around on this topic and only found examples/discussions centering on simple java chat applications. None that go into detail about protocol design (which I ultimately intend to practice).
Thanks to any help...
Second approach is much better, because serialization is a complex mechanism, that can be easily used in a wrong way (for example you may bind yourself to internal content of a concrete serialized class). Plus your protocol will be bound to JVM mechanism.
Using some "protocol header" for message differentiation is a common way in network protocols (FTP, HTTP, etc). It is even better when it is in a text form (people will be able to read it).
You typically have a little message header identifying the type of content in all messages, including standard text/chat messages.
Either of your two suggestions are fine. (In your second approach, you probably want to reserve some bytes for the length of the array as well.)

How can I send data in binary form over a Java socket?

I've seen lots of examples of sending serialized data over sockets in Java, but all I want is to send some simple integers and a string. And, the problem is I'm trying to communicate these to a binary written in C.
So, bottom line: how can I just send some bytes over a socket in Java?
You can use the simple OutputStream given by the Socket.
From there you can write bytes.
If you want you can also encapsulate this stream in a BufferedOutputStream to have a buffer.
I would really recommend not using the Java Sockets library directly. I've found Netty (from JBoss) to be really easy to implement and really powerful. The Netty ChannelBuffer class comes with a whole host of options for writing different data types and of course to can write your own encoders and decoders to write POJOs down the stream if you wish.
This page is a really good starter - I was able to make a fairly sophisticated client/server with custom encoders and decoders in under 30 minutes reading this: http://docs.jboss.org/netty/3.2/guide/html/start.html.
If you really want to use Java sockets. The socket output stream can be wrapped in a DataOutputStream which allows you to write many different data types as well, for example:
new DataOutputStream(socket.getOutputStream()).writeInt(5);
I hope that's useful.
I would recommend looking into Protocol Buffers for the serialization and ZeroMQ for the data transfer.

Categories

Resources