CorruptedFrame exception , websockets in Netty - java

I was just playing around the websocket example client and server on netty wiki.
I modified the way server sends data to client.
Suddenly i started getting exception like "io.netty.handler.codec.CorruptedFrameException: bytes are not UTF-8"
This is on client and i am creating frame on server like this :-
ByteBuf buf = Unpooled.buffer();
buf.writeShort(1);
channel.write(new TextWebSocketFrame(buf))
I understand from error that bytebuf must be UTF-8 encoded , even the constructor of TextWebSocketFrame says this.
But i have no clue on why i am getting this error.
Any suggestions ?

You are getting this as you try to send non UTF-8 data. If you want to just send any binary data use a BinaryWebSocketFrame.

Related

Write Timeout while writing bytes to web socket in apache tomcat

I have Java web socket web application. The websocket endpoint interacts with mobile clients. In one of the use case, the web application needs to write bytes of the size of 10MB or more to the web-socket outputstream. Following is the code which writes to the output stream :
if (webSocSession.isOpen()) {
webSocSession.getBasicRemote().sendBinary(byteBuffer);
byteBuffer.clear();
}
I am getting the following exception at times when the writing to the web-socket :
IOException writing to web-socket
java.io.IOException: java.net.SocketTimeoutException: Write timeout
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:324)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:259)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytes(WsRemoteEndpointImplBase.java:131)
at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:43)
at test.web.websocket.LIMSEndpoint$SocketWorker.writeToWebSocket(LIMSEndpoint.java:1188)
at test.web.websocket.LIMSEndpoint$SocketWorker.run(LIMSEndpoint.java:1127)
Caused by: java.net.SocketTimeoutException: Write timeout
at org.apache.tomcat.util.net.SocketWrapperBase.vectoredOperation(SocketWrapperBase.java:1458)
at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:1376)
at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:1347)
at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:93)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:509)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:311)
I tried setting the up the following SEND timeout property to 0 ( infinite write timeout ) , but it does not help. The following Apache Tomcat doc helped - https://tomcat.apache.org/tomcat-8.5-doc/web-socket-howto.html
org.apache.tomcat.websocket.BLOCKING_SEND_TIMEOUT
The web socket session max idle timeout has been set to 0 ( not to timeout )
Session.setMaxIdleTimeout(0)
Any help in this regard will be great help.
I would suspect that the clients receive buffer is filled up and it cuts the connection. I know this will happen the other way around, when a client sends large data to an apache server and the server isn't configured to have an extended binary buffer. See: org.apache.tomcat.websocket.binaryBufferSize
Perhaps you can get around the problem by sending the data in smaller chunks, sendBytes have a partial version.
https://tomcat.apache.org/tomcat-10.0-doc/websocketapi/index.html?jakarta/websocket/Session.html

Java won't deserialize object after it is sent through socket stream

I'm trying to create application that will send object through local network using Sockets. When i run server and client code in Intellij Idea they work fine, but when i run server code on one pc and client code on another pc i get errors like java.io.StreamCorruptedException: invalid type code: 00 or java.io.StreamCorruptedException: invalid stream header: 6C69656E
byte[] readBuffer = new byte[4096];
int num = inStream.read(readBuffer); //inStream is socket input stream
ByteArrayInputStream bis = new ByteArrayInputStream(readBuffer);
ObjectInput in = new ObjectInputStream(bis);
Object o = in.readObject(); //this line throws error
The thing is that writing and reading object to socket stream works on server (which is on pc where i created project) but reading from input stream on client (another pc where i copied project) throws error.
Can someone help me with this? I searched everywhere for solution but i can't figure out what is problem with serializing, because it works on same pc but won't on another. Is there any way that i can make this pc independent? This also happens when i create jar files and run it on same pc where it works in Intellij Idea.
It can because that client didnt read message fully.
But the real mistake is that you work with TCP socket like a message protocol transport but TCP is a stream protocol so you have to create your own message protocol on top of TCP.
Why it works fine on local system?
Because transport data between client and server happen too fast in local test and maybe in just one frame so all the message transported in just one IO-call but in internet or a network it doesn't work like you think.
There is 2 way to handle this mistake:
1- Pass SocketInputStream directly to ObjectInputStream instance and let it handle read objects.
2- Create a message protocol for example you can put the size of message in 2 or more first bytes. Then you can workd like this :
Read 2(or more) first bytes and detect size of packet.
Create a buffer for this size and read packet bytes.(make sure you read all of packet data from socket . You can use return value of SocketInputStream.read(byte[]) method to calculate it)
Pass the packet to ObjectInputStream and read object !

Java InputStream throwing java.io.StreamCorruptedException

I have a problem that I do not quite understand. I have a server socket and a client socket on two separate machines. Server will constantly sends out data in hex and connected client will read the data stream and do some work.
Most of the traffic is happening in that manner. On a few rare occasions, client will send a bytestring to Server. At this point, I am getting
Java.io.StreamCorruptedException at this line:
ObjectInputStream in = new
ObjectInputStream(socketFromClient.getInputStream());
Exception:
java.io.StreamCorruptedException: invalid stream header: 020001B5
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:857)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:349)
at ReadInput.run(ReadInput.java:21)
at java.lang.Thread.run(Thread.java:745)
"020001B5" is exactly the bytestring that client is sending over to server.
I do not understand why I am getting this StreamCorruptedException. My
code logic does not have any "stream header". What is stream header?
I checked javadoc and I could not make out of why this is happening.
Any tip much appreciated.
thanks
-v
Your client is not writing data using ObjectOutputStream: that's why you're seeing this exception. ObjectOutputStream and ObjectInputStream are used for serializing and deserializing Java objects.
Instead of using ObjectInputStream to read data, consider using BufferedReader or a DataInputStream.
See this example for more details.

Java TCP packets via HTTP proxy

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.

Writing a WebSocket Server

I'm trying to write a WebSocket Server in both, java and C++ but I'm stuck right now.
Using java and java.net.ServerSocket/java.net.Socket I managed to get a connection and succesfully do the handshake but the data sent by the WebSocket to the Java Server is not quite what I expected.
When sending messages from javascript like this:
var count = 0;
function loop(){
websocket.send("loop: " + count + "\n");
count++;
setTimeout(loop, 100);
}
The Java server receives this, with line feeds every now and then but not for every websocket.send() that has been invoked.
?‡½÷"˜Ñ˜Mè‡×?‡AÎ3-¡C{îN?‡ŒÍ[Uà¢4%¶íi?‡$ÍåøH¢ŠˆíÖ?‡·†ÞžÛé±î?¦ê?‡'½Ø…KÒ·õ?í?‡dÒÛ‘½´á^òí?‡+ù?YG–â)Ùº?‡›?
Ë÷àb»¡¯5?‡mÉŒQ¦ã!Wéµ?ˆ:J FV%f6
The Java server retrieves values from the socket using BufferedReader.readLine()
BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line =socketReader.readLine();
This works fine for the handshake and all handshake data is readable but it does not work after the handshake is done.
Is the data after the handshake somehow encrypted? How can I read it?
EDIT :
The program files:
SocketConnectTest.html
ServerTest.java
ClientSessionTest.java
ResponseGenerator.java
output
Just run ServerTest.java and then open SocketConnectTest.html.
ClientSessionTest.initClientListener() handles the messages from the client.
SOLUTION :
For the solution see pimvdbs post below and his answer at How to (de)construct data frames in WebSockets hybi 08+?
The data coming across web sockets is raw, not string encoded data.
I'd suggest not wrapping a BufferedReader around the incoming data as packets are framed with 0x00 bytes. The crazy characters you are seeing are a result of Java not understanding the encoding that the data is in.
You will need to be responsible for splitting up the data into character and control parts. Once you've split the data up into the appropriate areas, then you can decode the data as a string.

Categories