3

I've developed a websocket server in java from scratch. The javascript client is running in browser:

function connectToServer() {
    connection = new WebSocket("ws://" + document.domain + ":8351");       
    connection.onopen = function () {
    };

    connection.onmessage = function (e) {
        handleServerResponse(e.data);
    };
}

Everything is fine until the messages (json) reach 65535 bytes. Then the socket is closed (i have not figured out, if client or server closes the connection.

In browser console (tried several browsers) I see: The connection to ws://localhost:8351/ was interrupted while the page was loading.

On server side, I see: java.net.SocketException: Connection reset at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)

So, if the problem is in handshake or I build the frame incorrectly in server and the client closes the connection or I'm writing the bytes to stream incorrect and the java io closes the socket.

My code (server):

1) Handshake (server response)

  String _01 = "HTTP/1.1 101 Switching Protocols\r\n";
  String _02 = "Upgrade: websocket\r\n";
  String _03 = "Connection: Upgrade\r\n";
  String _04 = "Sec-WebSocket-Accept: " + responseKey + "\r\n";
  String _05 = "Content-Encoding: identity\r\n";

2) Building the frame (Should large messages be broken up to different frames?)

public static byte[] buildFrame(String message)
{
    int length = message.length();
    int rawDataIndex = -1;
    if (length <= 125)
        rawDataIndex = 2;
    else if (length >= 126 && length <= 65535)
        rawDataIndex = 4;
    else
        rawDataIndex = 10;
    byte[] frame = new byte[length + rawDataIndex];
    frame[0] = (byte)129;
    if (rawDataIndex == 2)
        frame[1] = (byte)length;
    else if (rawDataIndex == 4)
    {
        frame[1] = (byte)126;
        frame[2] = (byte)(( length >> 8 ) & (byte)255);
        frame[3] = (byte)(( length      ) & (byte)255);
    }
    else
    {
        frame[1] = (byte)127;
        frame[2] = (byte)(( length >> 56 ) & (byte)255);
        frame[3] = (byte)(( length >> 48 ) & (byte)255);
        frame[4] = (byte)(( length >> 40 ) & (byte)255);
        frame[5] = (byte)(( length >> 32 ) & (byte)255);
        frame[6] = (byte)(( length >> 24 ) & (byte)255);
        frame[7] = (byte)(( length >> 16 ) & (byte)255);
        frame[8] = (byte)(( length >>  8 ) & (byte)255);
        frame[9] = (byte)(( length       ) & (byte)255);

    }
    for (int i = 0; i < length; i++)
        frame[rawDataIndex + i] = (byte)message.charAt(i);
    return frame;
}

3) Writing bytes to socket (I've tried socket.setSendBufferSize and BufferedOutputStream, nothing helps)

socket.getOutputStream().write(byteMessage);
socket.getOutputStream().flush();

Has anyone encountered the same problem? Any help is welcome!

user2576225
  • 51
  • 1
  • 4
  • "Connection reset" means that the remote side closed the connection when you were trying to send data. What do you use as the client? Does it allow packets with more than 64k of data? – Joni Jul 17 '13 at 07:48
  • It's a javascript client (Updated the question) Can I somehow configure it to accept large messages? – user2576225 Jul 17 '13 at 07:51

2 Answers2

5

I know it's a bit late for answering... but anyway, i faced the same problem and this code:

    frame[1] = (byte)127;
    frame[2] = (byte)(( length >> 56 ) & (byte)255);
    frame[3] = (byte)(( length >> 48 ) & (byte)255);
    frame[4] = (byte)(( length >> 40 ) & (byte)255);
    frame[5] = (byte)(( length >> 32 ) & (byte)255);
    frame[6] = (byte)(( length >> 24 ) & (byte)255);
    frame[7] = (byte)(( length >> 16 ) & (byte)255);
    frame[8] = (byte)(( length >>  8 ) & (byte)255);
    frame[9] = (byte)(( length       ) & (byte)255);

works. Your problem here is that your variable "length" is an int that is 32bits. And you are performing bit shifting on 8 bytes so you get random data from the memory. If you define your variable "length" as a 64 bits long then it works.

long length = (long)message.length();

worked perfectly for me.

I hope it can help someone who wants to understand.

user3892585
  • 51
  • 1
  • 3
2

As I suspected, the bit-shifting code, populated over the internet does not work.

Found the following code (source) :

 frame[1] = (byte)127;

            int left = length;
            int unit = 256;

            for (int i = 9; i > 1; i--)
            {
                frame[i] = (byte)(left % unit);
                left = left / unit;

                if (left == 0)
                    break;
            }

And it works! Although I could not figure out, what's the difference.

Community
  • 1
  • 1
user2576225
  • 51
  • 1
  • 4