I want to send a message via a java.net.Socket.
The message is: 001C020000C0154C000404850D9583CC00000004560B00E42080004C
For my application I need this message to be sent via one TCP packet.
But checking Wireshark what is happening is, I can see, that it divides the message into
two reassembled SSL segments:
00
1C020000C0154C000404850D9583CC00000004560B00E42080004C
How can I supress this behavior?
My code is:
OutputStream os = m_sslsocket.getOutputStream();
os.flush();
write(hex2Byte("001C020000C0154C000404850D9583CC00000004560B00E42080004C");
os.flush();
where hex2Byte converts the hexadecimal String to a bytearray.
EDIT:
Thank you for your comments.
In any case my protocol stack when observing via WireShark looks as follows:
As you can see there are two SSL Segments, where one is with 00
and the other has the rest.
How to supress it such, that there is only one segment?
The above is the result of my writing to the outputstream.
(Do not worry about the red. That is just because of IP checksum offload to the network device.)
For my application I need this message to be sent via one TCP packet.
Bad luck, TCP cannot be made to do that reliably, with or without SSL. Adjust your expectations. It's a byte-stream protocol.
Related
Hi let me get straight to the problem. I have a big JSON packet that the server sends to this client once the client is authenticated
But the packet comes back in a weird way like it's split or something example:
The JSON should be:
Received: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0,"ItemSlots":30}
When it comes through:
Received: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0,
Received: "ItemSlots":30}
Why does it split the packet or something when it comes to the client and how can I fix this anyway?
Java Receive Code:
private class ClientThread extends Thread {
public void run() {
try {
while (selector.select() > 0) {
for (SelectionKey sk : selector.selectedKeys()) {
selector.selectedKeys().remove(sk);
if (sk.isReadable()) {
SocketChannel sc = (SocketChannel)sk.channel();
ByteBuffer buff = ByteBuffer.allocate(1024);
String content = "";
while (sc.read(buff) > 0) {
sc.read(buff);
buff.flip();
content += charset.decode(buff);
buff.clear();
}
System.out.println("Recieved: " + content);
sk.interestOps(SelectionKey.OP_READ);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks have a wonderful day.
Hi lemme get straight to the problem so i got a big JSON packet that the server sends to this client once the client is authenticated
You mean you have a big JSON message. Packets are things that network protocols used to exchange information.
But the packet comes back in a weird way like its split or something example:
Unless you're looking at the wire, you aren't looking at packets. You're looking at the bytes you got from your end of the TCP connection.
The JSON should be:
Recieved: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0,"ItemSlots":30}
When it comes through:
Recieved: {"UserID":1,"PlayerID":2,"EXP":0,"Lvl":1,"Coins":0,
Recieved: "ItemSlots":30}
Excellent. You got the same bytes. Now make a JSON parser that figures out where the message ends and parses it.
Why does it split the packet or something when it comes to the client
It splits the message into packets because that's how TCP gets the message to the other side. TCP is not a message protocol and it doesn't know or care what the application considers to be a message -- that's the application's job.
and how i can i fix this anyway?
Write a JSON parser to figure out where the messages end. You haven't implemented any code to receive JSON over TCP yet, so that won't work until you do.
TL;DR: If you want an application-level message protocol, you need to implement one. TCP is not one.
TCP protocol does not maintain message boundaries. It is not guaranteed that what the server sends is received as-is by the client and vice-versa.
If the server sends 1000 bytes data, the client application can receive the same across multiple recv or single recv. TCP does not guarantee any behaviour. "Split" can happen, it is upto the application to handle the data coming in multiple chunks, coalesce it to one unit of application data for further processing. One can see this particularly with large data sizes.
It looks like you've got a non-blocking socket channel, meaning that the while (sc.read(buff) > 0) { loop is terminating due to sc.read(buff) returning 0 since only a portion of the data sent has, at this point, been received.
Why does it split the packet or something when it comes to the client
Most likely the data is being split into two or more packets.
and how i can i fix this anyway?
Keep filling your buffer until the socket is closed by the server (read should return -1 rather than 0 in that case). You need to maintain a separate buffer per channel. If the server doesn't close its end after sending the data, you'll need to delineate in some other way; you could prefix the JSON blob with a size header, for instance.
I've searched high and low and havn't been able to find an answer to this question. I'm fairly certain that it isn't difficult, probably a case of my searches not using the right verbiage.
I'm working on communicating with a gimbal controller. I've been able to connect to the serial port that it's connected to. I'm unable to find information on how to format a message like this:
Each command consists
of the header and the body, both with checksum. Commands with the wrong header or body checksum, or
with the body size that differs from expected, should be ignored.
Can anyone point me in the direction on how to write to the serial port like that?
Thank you,
Loren
There are two typical approaches for communicating with a device over a serial port. In both cases, the end result is raw bits being sent over the wire. You can send ASCII strings if your device expects it but since your excerpt specifically mentioned packet packaging, I would venture to say that they want bytes.
The excerpt you copy pasted sounds like it came from a manual that explains the exact protocol that is required to communicate. In a nutshell, you will be doing the following.
Setup the serial port
Prepare your serial data
Send your serial data
I like to use jSSC for serial comms though lots of other folks use RXTX. jSSC has been more reliable for me so that's what I'll be using in my example. The manual for your device should specify the required baud rate, data bits, stop bits, parity, and handshake (if any).
Here we setup a port (replace your parameters as needed). See the docs on the details of this. https://github.com/scream3r/java-simple-serial-connector
SerialPort _port = new SerialPort(portName);
_port .openPort();
_port.setParams(baudRate, dataBits, stopBits, parity, setRTS, setDTR);
_port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
To construct your data packet, you will need to know:
Header format
Length requirement/restrictions
Checksum method
Here I am going to make a super simple packet that is just an example and is most likely not applicable to your use case.
// Format is: [length][7 data bytes][8 bit additive checksum]
// Create an empty byte array
byte[] packet = new byte[8];
// Our simple header
packet[0] = packet.length;
// Some data
byte[] dummyData = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
// Copy data to packet
System.arraycopy(dummyData, 0, packet, 0, dummyData.length);
// Go do the checksum (good exercise for you)
byte checksum = getChecksum(packet);
packet[7] = checksum;
So now we have a port, some data... and now what? Let's send it.
// Just send those bytes
_port.writeBytes(packet);
Once you get the hang of things, read into how you read the response, setup OnDataReceivedEvents, and how to more efficiently create packets. Some good terms to Google:
jSSC
Java RXTX
Baud Rate
Async/Sync data handling
I am sending TCP packets just few bits each (one line of text or so). I am sending them to remote server via HTTP proxy however for some reason when the connection with the proxy is slow or interrupted to the server arrives just a fragment of the packet and not entire packet and it causes exceptions on the server side, how it that posible ? Is there any way on the client side how to prevent sending fragment of the packet instead of entire packet ?
Example: I am trying to send this packet:
packetHead: id (1-99)
integer: 1
short: 0
byte: 4
And in my case sometimes happens that to the server arrives just packetHead and integer and the rest of the packet is lost somewhere when the connection with the proxy is bad.
I have no access to modify server source code so I need to fix it on the client side.
Thanks for any tips.
Please show how you send your data. Every time I had a similar problem it was my fault for not flushing the stream. Especially if the stream is compressed you need to call close/complete on the GZIP or similar object to actually send out everything.
I'm trying to make a port of a chat program a friend of mine made with lacewing and multimedia fusion 2 for android device.
I've managed to create a socket connecting to the listening socket of the server successfully, but I cannot seem to be able to send data to login and enter the chat. The login for now just requires a name, but even if I send a String of data, the server doesn't seem to reply or accept that data to get me over the channel.
I know I could easily port this with other way like using the NDK of the multimedia fusion 2 exporter, but I just want to figure out how this works
PS: I'm using Java and libgdx for the development
You need to read the liblacewing relay protocol:
https://github.com/udp/lacewing/blob/0.2.x/relay/current_spec.txt
On initial connection, you have to send byte 0 to identify that you are not an HTTP client. After this, you can exchange normal protocol messages.
The first message you need to send is the connection request (which may be denied by the server with a deny message). This would be:
byte 0 (2.1.0 request)
(1.2 size)
byte 0 (2.1.0.0 connection request)
string "revision 3" (2.1.0.0 connection request -> version)
When the server responds with response 0 (2.2.0.0 Connect), you then have to set a name before you may join any channels. This is done with message 2.1.0.1 SetName, which is the same structure as above but instead of 2.1.0.0's byte 0, it is 2.1.0.1's byte 1, followed by the name as a string instead of the protocol version.
The server should then respond with 2.2.0.1 SetName, assuming it accepted your name change request. You should process this message in case the server gave you a different name than you requested. Finally, once you have a name, you can join a channel with 2.1.0.2 JoinChannel. The flags you specify here will be used if the channel doesn't exist yet (e.g. nobody is in the chat yet) - these should match the ones in the MMF2 project file. The name should also match.
After all that, you're still not done! You have to process more messages, etc. it's almost like writing the RelayClient class yourself. It's a tough task, but with the protocol specification in hand you should be able to work it all out.
I built a tcp server based on apache mina 2.0.4, and have some problems writing back to the client.
We have some tcp clients that can handle only one message at a time and with a buffer size of 256 bytes max. When I send 2+ messages (< 256 bytes) to the client, they arrive in one or two big blocks that the client can't handle, instead of 2+ separated messages.
I tried to set sessionConfig.setTcpNoDelay(true/false); with no success, as well as sessionConfig.setSendBufferSize( 256 );.
In the message response encoder I also tried to flush the output:
int capacity = 256;
IoBuffer buffer = IoBuffer.allocate(capacity, false);
buffer.setAutoExpand(false);
buffer.setAutoShrink(true);
buffer.putShort(type);
buffer.putShort(length);
buffer.put(gmtpMsg.getMessage().getBytes());
buffer.flip();
out.write(buffer);
out.flush();
And in the thread responsible to send the messages, I tried to wait for the message to be written
for (Entry<Long, OutgoingMessage> outgoingMsg : outgoingMsgs.entrySet()) {
WriteFuture future = session.write(outgoingMsg.getValue());
future.awaitUninterruptibly();
}
All this fails miserably, and the only solution working is a ridiculous 500 msec sleep between the session write, which is hardly acceptable.
Anyone see what I am doing wrong?
After reading a bit more on the tcp protocol and specially https://stackoverflow.com/a/6614586/1280034, it is clear that the problem is on the client side, not handling the packets correctly.
Since we can't rebuilt the clients, my only solution is to delay each outgoing messages by approx 500ms. To do so I created an extra queue in charge of the writting to clients in order to let the server continue its normal job.