I made multiclient chat that is working pretty well. I am sending data through PrintWriter and receiving them using BufferedReader. As far as they are characters everything goes fine. But I though about adding possibility to send voice, too. And here I faced the problem. I have already used socket input and output stream and using them for transmitting characters. How to solve this problem and make sending bytes also possible? Isn't possible to create second stream that would be responsible for transmitting bytes? It would make things much more easier . If not how to solve it otherway?
I would not use TCP for voice transmitting, see the differences between TCP and UDP.
However, you can mix it by sending bytes only and converting all char-messages to byte-messages? I would not mix the writers streams.
In your case I'd simply open another socket.
Since you're considering VoIP, you might want to consider a UDP socket instead of TCP (assuming you use TCP for your chat).
But remember that in the end you always send bytes over a socket; it doesn't matter if it's text or voice data; text strings are also converted to bytes.
Related
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.
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.
This is the situation:
I'm working on a project where I need to be able to send one or more images once in a while to/from the server as well as a lot of other types of data represented with text. The way it is currently done, is by sending a message with that says "incoming image of size x to be used as y" (It's not "formulated" that way of course), and then I call a method that reads the next x bytes through a DataInputStream. At first I met some problems with latency screwing things up, but I made the server spawn a new thread to send the "incoming image" message, and then wait for a flag that is set when the client responds with a "I'm ready for the image" message. It works in a way now, but if anything else, for instance a chat message, is sent while the image is being transfered, that message meant for a BufferedReader will be read as raw bytes and used as part of the image. So I will have to block all outgoing data (and add it to a queue) when there is an image that is being sent. But this seems very wrong and annoying, as users of the application will not be able to chat while receiving/ uploading a big image.
This is what I need:
So, I either need to set up an independent channel to use for raw data. Which, as far as I understand from some tinkering, I will have to set up a new socket over a new port, which seems unnecessary. The other way I can see to solve this, would be to somehow use tag each packet with a "this is text/raw data" bit, but I have no idea how to do this with java? Can you add information to the packet-header when you write something to the stream (that every packet containing that info will contain) and then read the packet data on the other end and act accordingly?
As you can see, I do not have much experienced with networking, nor have I used Java for a long time. This is also my first post here, so be kind. If anything was unclear, please ask, and I'll specify. All ideas are welcome! (There is possibly a standard way to do this?)
Thanks a lot!
There is nothing in TCP protocol itself that can help you.
You either open a new socket connection (can be to the same server port), or you split your images in, smaller chunks and wrap these chunks in envelopes saying what type of message it is: image or chat. And then reconstruct the image on the receiving end from these chunks. But this will waste bandwidth and add complexities of its own (e.g. how big do you make a chunk of that image?).
I would go with the separate binary data connection.
Java should have a standard support for HTTP protocol - use HTTP to do your picture transfers as you can set the type of data being transmitted in the header. Basically, you would have your client/server architecture establish a separate request for each new data transfer (be it text or image), that way enabling you to do processing in a simple loop.
This might be of some help to you : How to use java.net.URLConnection to fire and handle HTTP requests?
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.
I've been reading some Java socket code snippet and fonund out a fact that in socket communication, to send messages in sequence, you don't have to seperate them by hand, the writer/reader stream do the things automatically for you. Here is an example:
writer.java
writeUTF("Hello");
writeUTF("World");
reader.java
String a=readUTF(); // a=Hello
String a=readUTF(); // b=World
I've tried this code snippet and it works fine. However, I'm wondering whether this kind of coding style is supposed to be working fine. Is there any potential risks of using the socket stream in sequence without explicitly seperating each segment?
The writeUTF() and readUTF() write the length of the String (in bytes, when encoded as UTF-8) followed by the data, and use a modified UTF-8 encoding. So there are some potential problems:
The maximum length of Strings that can be handled this way is 65535 for pure ASCII, less if you use non-ASCII characters - and you cannot easily predict the limit in that case, other than conservatively assuming 3 bytes per character. So if you're sure you'll never send Strings longer than about 20k, you'll be fine.
If the app ever needs to communicate with something else (that's not written in Java), the other side may have a hard time handling the modified UTF-8. For application-internal communication, you don't have to worry though.
According to the documentation the readUTF and writeUTF methods work with a modified version of UTF8 that also adds the length of the character to be read in the beginnig.
This should mean that the read operation will wait until enough characters had been fetched before returning the string.. this means they are actually segmented also if you don't see it since you merely decorate the streams of the socket with the DataInputStream and DataOutputStream.
In conclusion, yes, it should be quite safe, since the API itself will take care of separating the single messages.
java.net.Socket works fine, the stream waits readUTF();
But when using mina's CumulativeProtocolDecoder, it won't, throws java.io.EOFException