I'm using the java AsynchronousSocketChannel from nio2 in my project. I'm using oracle jdk 1.7.0_80 on ubuntu 14.04 too.
My project is a server that processes binary data.
The code calls the read operation recursively in the completed method of the CompletionHandler anonymous class, like this:
private final CompletionHandler<Integer,AsynchronousSocketChannel> readHandler=new CompletionHandler<Integer,AsynchronousSocketChannel>(){
#Override
public void completed(Integer result,AsynchronousSocketChannel attachment) {
if(result<0){
attachment.close();
return;
}
attachment.read(swap, attachment, this);
}
}
Where the variable swap is a ByteBuffer instance.
Apparently, everything works well. But, there is a packet whose total size is 3832 bytes, when the server receive this whole packet, without segments, there is no problem. However, sometimes this packet is divided in two or more parts (TCP segments). eg: The size of first segment is 2896 bytes and the size of second is 936 bytes.
The last segment doesn't have a header, this is breaking my algorithm.
I would like know, is there a way to do the API calls the "completed" method only after reading the whole packet?
I have increased the SO_RCVBUF to 64K, but it doesn't work.
I would like know, is there a way to do the API calls the "completed" method only after reading the whole packet?
No, there is no way to do this.
The TCP protocol can break up your stream of bytes in packets of arbitrary size. The application-level protocol that you use on top of TCP must not rely on messages always being sent completely in one TCP packet.
You must design your application-level protocol in such a way that it can deal with messages arriving broken up in packets of arbitrary size.
One common way to do this is to prefix application-level messages by a length field. For example, an application-level message consists of a field of 4 bytes that contain the length of the rest of the message. When you receive a message, you first receive the length, and then you should keep on receiving until you have received that many bytes, which you can then assemble into an application-level message.
The AsynchronousSocketChannel API cannot re-assemble application-level messages automatically for you, because it does not know anything about your application-level protocol.
Related
Can I parallelly connect many independent I/O streams of server's socket and client's socket such that each pair of I/O streams could send different data at the same time ?
How could I achieve such a connection in java without increasing number of sockets between server and client?
There's always one stream for input and one stream for output, so you can't add more streams.
However, as sje397 commented, you can use the same stream to send "different" data, you just need to come up with a way to distinguish the channels in the receiving side, so it can reconstruct the data properly. This is a protocol design issue.
Edit:
In your example you could have a packet structure with a header that tells the type (or channel) of the packet, length of the data and for the file packets some additional information if needed. Let's assume that the length field is a single byte, so your maximum packet size (for String packets) would be 1 + 1 + 255 = 257 bytes.
When the server reads bytes, it will check the first byte for the type of the packet. After determining that it's a String packet, it will read the length, then read the payload. Then the process repeats itself.
For file data additional header information is most likely needed, otherwise the non-String packets will just be a bunch of bytes.
This means that your protocol will become packet based, so you must write the data one packet at a time. Assuming that a data packet has a max size of 64K, you would then be able to send data in the following way (imagine that it's a network pipe):
Client -> 257(S) -> 64K(D) -> 257(S) -> 64K(D) -> 257(S) -> Server
allowing you to interleave the two different kinds of data in a single network connection.
Assuming that you want fast replies for console input, my suggestion to use two socket streams - one for file data and another for user input. You can use ObjectInputStream and ObjectOutputStreams to simplify your protocol. Just create a class for your protocol make it serializeable and use it with socket streams.
I am trying to communicate between two computers using the Serial port and I am new to this area. I need to send requests from one computer(say A) to the other(say B) and receive responses for the requests sent. I am updating a Java Swing user interface with the responses.
I am using the jSSC library to do this. I have looked at the SerialPortReader examples and following is my understanding.
I will have to implement the SerialPortEventListener on both computers.A will use the writeBytes method to send the requests. B will listen to the commands sent using the SerialPortEventListener and will use the writeBytes method to send the response. A will listen to the data using its implemntation of SerialPortEventListener and when data is recieved, will update the UI. The following are my questions.
a) Is my above observation correct? Is there a different way to do this(for example is it possible that a writeBytes method that will return the response exists within the protocol?)
b) I read in several paces that serial port communication can be either synchronous or asynchronous. But from the examples, I can't understand if that code has implemented an asynchronous or synchronous communication. How would one go about implementing synchronous/asynchronous communication using jSSC? I am not asking for an implementation. Just some guidelines and what methods can be used.
c) It's possible that messages will be partly delivered. For example, if I send the command as a String "get variableThreeValue", it is possible that only the "get" or something like "get varia" will be received.(this can result in messages like "get get" etc..) How can I handle this kind of scenario? Again, I am not asking for an implementation. Just some guidelines and what methods can be used.
A classic "serial port" is something very "low level". Parameters like baud rate, start and stop bits and flow control must be set, and then byte sequences are read and written. The Java library uses a listener to receive events which are directly derived from what the serial driver senses (you find terms like "line" in the javadoc). How to react, depends on "the other side".
Flow control is what you use to avoid overrunning or overfilling the receiver. The lines of an RS-232 contain C(lear)T(o)S(end) and R(equest)TS, so "hardware handshake" is one option. Alternatively, US-ASCII defined control characters XON and XOFF which could be embedded in the data stream if it is not binary data. Flow control should not be an issue if the sending end doesn't send at full blast or computers differ significantly in speed.
As I understand, you'll connect some radio device to the port, and its documentation should specify all the parameters, and also the higher level protocol, i.e., how to transmit and receive data. The device may have special requirements, e.g., that you must pass on some setup data before you transmit actual data. (If you connect two computers with just a cable, then everything is up to you.)
Once you can basically send and receive, you'll have to think about safe transmission. You need to design a protocol:
message format, e.g. containing a length, a sequence number, data bytes, a CRC.
message sequencing, i.e., who may send what and when, e.g., a message A to B, an acknowledge from B to A, repeat. Or a NAK from B, and A must resend.
Perhaps you need a "session protocol", i.e., a login (as in ftp) and a logout
Timeout: what if either side doesn't receive another message within T?
Do you need a heartbeat, i.e., a message sent when the channel is idle to learn that the other side is still "alive".
A WLAN connection should make most of this unnecessary. Real "radio" (some short wave?) I've never heard of, but I'm not a radio expert.
XON/XOFF is software flow control. Assume bi directional serial bytes between producer a and b. If either sends a XON byte it means whoa, stop sending me bytes until I send you a XOFF byte.
For hardware replace XON byte with CTS and XOFF byte with RTS.
I've read some conflicting things about how UDP/Java datagram channels operate. I need to know a few things:
Does UDP have an inherit way to tell if the packet that is received whole, and in order, before .read(ByteBuffer b) is called? I've read in at least one article saying that UDP inherit'ly discards incomplete or out of order data.
Does datagramchannel treat one send(buffer.. ) as one datagram packet? what if its a partial send?
Can a .read(.. ) read more than one packet of data, resulting in data being discarded if the buffer being given as the commands argument was only designed to handle one packet of data?
Does UDP have an [inherent] way to tell if the packet that is received whole, and in order, before .read(ByteBuffer b) is called? I've read in at least one article saying that UDP inherit'ly discards incomplete or out of order data.
Neither statement is correct. It would be more accurate to say that IP has a way to tell if a datagram's fragments have all arrived, and then and only then does it even present it to UDP. Reassembly is the responsibility of the IP layer, not UDP. If the fragments don't arrive, UDP never even sees it. If they expire before reassembly is complete, IP throws them away.
Before/after read() is called is irrelevant.
Does datagramchannel treat one send(buffer.. ) as one datagram packet?
Yes.
what if it's a partial send?
There is no such thing in UDP.
Can a read(.. ) read more than one packet of data
A UDP read will return exactly and only one datagram, or fail.
resulting in data being discarded if the buffer being given as the commands argument was only designed to handle one packet of data?
Can't happen.
Re your comment below, which is about a completely different question, the usual technique for detecting truncation is to use a buffer one larger than the largest expected datagram. Then if you ever get a datagram that size, (i) it's an application protocol error, and (ii) it may have been truncated too.
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.
I am currently using a non-blocking SocketChannel (Java 1.6) to act as a client to a Redis server. Redis accepts plain-text commands directly over a socket, terminated by CRLF and responds in-like, a quick example:
SEND: 'PING\r\n'
RECV: '+PONG\r\n'
Redis can also return huge replies (depending on what you are asking for) with many sections of \r\n-terminated data all as part of a single response.
I am using a standard while(socket.read() > 0) {//append bytes} loop to read bytes from the socket and re-assemble them client side into a reply.
NOTE: I am not using a Selector, just multiple, client-side SocketChannels connected to the server, waiting to service send/receive commands.
What I'm confused about is the contract of the SocketChannel.read() method in non-blocking mode, specifically, how to know when the server is done sending and I have the entire message.
I have a few methods to protect against returning too fast and giving the server a chance to reply, but the one thing I'm stuck on is:
Is it ever possible for read() to return bytes, then on a subsequent call return no bytes, but on another subsequent call again return some bytes?
Basically, can I trust that the server is done responding to me if I have received at least 1 byte and eventually read() returns 0 then I know I'm done, or is it possible the server was just busy and might sputter back some more bytes if I wait and keep trying?
If it can keep sending bytes even after a read() has returned 0 bytes (after previous successful reads) then I have no idea how to tell when the server is done talking to me and in-fact am confused how java.io.* style communications would even know when the server is "done" either.
As you guys know read never returns -1 unless the connection is dead and these are standard long-lived DB connections, so I won't be closing and opening them on each request.
I know a popular response (atleast for these NIO questions) have been to look at Grizzly, MINA or Netty -- if possible I'd really like to learn how this all works in it's raw state before adopting some 3rd party dependencies.
Thank you.
Bonus Question:
I originally thought a blocking SocketChannel would be the way to go with this as I don't really want a caller to do anything until I process their command and give them back a reply anyway.
If that ends up being a better way to go, I was a bit confused seeing that SocketChannel.read() blocks as long as there aren't bytes sufficient to fill the given buffer... short of reading everything byte-by-byte I can't figure out how this default behavior is actually meant to be used... I never know the exact size of the reply coming back from the server, so my calls to SocketChannel.read() always block until a time out (at which point I finally see that the content was sitting in the buffer).
I'm not real clear on the right way to use the blocking method since it always hangs up on a read.
Look to your Redis specifications for this answer.
It's not against the rules for a call to .read() to return 0 bytes on one call and 1 or more bytes on a subsequent call. This is perfectly legal. If anything were to cause a delay in delivery, either because of network lag or slowness in the Redis server, this could happen.
The answer you seek is the same answer to the question: "If I connected manually to the Redis server and sent a command, how could I know when it was done sending the response to me so that I can send another command?"
The answer must be found in the Redis specification. If there's not a global token that the server sends when it is done executing your command, then this may be implemented on a command-by-command basis. If the Redis specifications do not allow for this, then this is a fault in the Redis specifications. They should tell you how to tell when they have sent all their data. This is why shells have command prompts. Redis should have an equivalent.
In the case that Redis does not have this in their specifications, then I would suggest putting in some sort of timer functionality. Code your thread handling the socket to signal that a command is completed after no data has been received for a designated period of time, like five seconds. Choose a period of time that is significantly longer than the longest command takes to execute on the server.
If it can keep sending bytes even after a read() has returned 0 bytes (after previous successful reads) then I have no idea how to tell when the server is done talking to me and in-fact am confused how java.io.* style communications would even know when the server is "done" either.
Read and follow the protocol:
http://redis.io/topics/protocol
The spec describes the possible types of replies and how to recognize them. Some are line terminated, while multi-line responses include a prefix count.
Replies
Redis will reply to commands with different kinds of replies. It is possible to check the kind of reply from the first byte sent by the server:
With a single line reply the first byte of the reply will be "+"
With an error message the first byte of the reply will be "-"
With an integer number the first byte of the reply will be ":"
With bulk reply the first byte of the reply will be "$"
With multi-bulk reply the first byte of the reply will be "*"
Single line reply
A single line reply is in the form of a single line string starting with "+" terminated by "\r\n". ...
...
Multi-bulk replies
Commands like LRANGE need to return multiple values (every element of the list is a value, and LRANGE needs to return more than a single element). This is accomplished using multiple bulk writes, prefixed by an initial line indicating how many bulk writes will follow.
Is it ever possible for read() to return bytes, then on a subsequent call return no bytes, but on another subsequent call again return some bytes? Basically, can I trust that the server is done responding to me if I have received at least 1 byte and eventually read() returns 0 then I know I'm done, or is it possible the server was just busy and might sputter back some more bytes if I wait and keep trying?
Yes, that's possible. Its not just due to the server being busy, but network congestion and downed routes can cause data to "pause". The data is a stream that can "pause" anywhere in the stream without relation to the application protocol.
Keep reading the stream into a buffer. Peek at the first character to determine what type of response to expect. Examine the buffer after each successful read until the buffer contains the full message according to the specification.
I originally thought a blocking SocketChannel would be the way to go with this as I don't really want a caller to do anything until I process their command and give them back a reply anyway.
I think you're right. Based on my quick-look at the spec, blocking reads wouldn't work for this protocol. Since it looks line-based, BufferedReader may help, but you still need to know how to recognize when the response is complete.
I am using a standard
while(socket.read() > 0) {//append
bytes} loop
That is not a standard technique in NIO. You must store the result of the read in a variable, and test it for:
-1, indicating EOS, meaning you should close the channel
zero, meaning there was no data to read, meaning you should return to the select() loop, and
a positive value, meaning you have read that many bytes, which you should then extract and remove from the ByteBuffer (get()/compact()) before continuing.
It's been a long time, but . . .
I am currently using a non-blocking SocketChannel
Just to be clear, SocketChannels are blocking by default; to make them non-blocking, one must explicitly invoke SocketChannel#configureBlocking(false)
I'll assume you did that
I am not using a Selector
Whoa; that's the problem; if you are going to use non-blocking Channels, then you should always use a Selector (at least for reads); otherwise, you run into the confusion you described, viz. read(ByteBuffer) == 0 doesn't mean anything (well, it means that there are no bytes in the tcp receive buffer at this moment).
It's analogous to checking your mailbox and it's empty; does it mean that the letter will never arrive? was never sent?
What I'm confused about is the contract of the SocketChannel.read() method in non-blocking mode, specifically, how to know when the server is done sending and I have the entire message.
There is a contract -> if a Selector has selected a Channel for a read operation, then the next invocation of SocketChannel#read(ByteBuffer) is guaranteed to return > 0 (assuming there's room in the ByteBuffer arg)
Which is why you use a Selector, and because it can in one select call "select" 1Ks of SocketChannels that have bytes ready to read
Now there's nothing wrong with using SocketChannels in their default blocking mode; and given your description (a client or two), there's probably no reason to as its simpler; but if you want to use non-blocking Channels, use a Selector