views:

64

answers:

2

Java Socket Server


I have a Java process that is creating a listener on a TCP Socket using java.io.ServerSocket something like this (simplified):

ServerSocket server = new ServerSocket(4444,20);
server.accept();

The Java Process Fires off a Worker Thread when a Request Is Received and the Worker then sends a JSON string using java.io.PrintWriter and java.net.Socket:

PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.println("JSON STRING");
out.flush();
out.close();
clientSocket.close();

I have simplified the Java code but this is essentially all it is doing.


.NET Socket Client


Next I have a .NET Application that communicates with the machine hosting this Java Process:

//Create Connection
Socket clientSocket = new Socket(AddressFamily.InterNetwork, 
                                 StreamType.Stream, ProtocolType.Tcp);
mySocket.Connect("192.168.1.102", 4444);

//Initialize Byte Buffer Larger than Expected JSON String and Read Bytes
byte[] receivedData = new byte[524288];
int numberOfBytes = clientSocket.Receive(receivedData, SocketFlags.None);
clientSocket.Close();

//Populate a new byte array of the exact size received with the received data
byte[] formatedBytes = new byte[numberOfBytes];
for (int i=0; i< numberOfBytes; i++)
{
    formatedBytes[i] = receivedData[i];
}

//Convert Byte Array to String & Output Results
Response.ClearContent();
Response.ContentType("text/plain");
Response.Write(new System.Text.ASCIIEncoding().GetString(receivedData));

My Issue is that for whatever reason, this implementation does not work when I attempt to send slightly larger JSON Strings over the Socket Stream. With small datasizes (under 2KB) I have successfully tested this implementation with over 100 Clients connecting and receiving data without any issues, however trying to increase the JSON String size to about 256KB results in the .NET Application truncating the results. Increasing the size of the byte buffer array does not help either - it seems as if the .NET application is dropping the connection before all the data is transmitted, or the Java Application is not sending the entire String using the PrintWriter.

Any insight into this issue would be greatly appreciated - I'll post any updates if I make any progress myself.


Here is the Solution I came to - Server Is Working Great Now! Thanks Again!


    byte[] receivedData = new byte[512000]; // 4 Meg Buffer

    Socket mySocket = new Socket(AddressFamily.InterNetwork, 
                               SocketType.Stream, ProtocolType.Tcp);
    mySocket.Connect("172.26.190.205", 4444);
    mySocket.ReceiveBufferSize = 8192;

    int numberOfBytesRead = 0;
    int totalNumberOfBytes = 0;
    do
    {
        numberOfBytesRead = mySocket.Receive(receivedData,totalNumberOfBytes ,
                            mySocket.ReceiveBufferSize,SocketFlags.None);
        totalNumberOfBytes += numberOfBytesRead;
    } 
    while (numberOfBytesRead > 0);
    mySocket.Close();

    byte[] formatedBytes = new byte[totalNumberOfBytes ];
    for (int i = 0; i < totalNumberOfBytes ; i++)
    {
        formatedBytes[i] = receivedData[i];
    }
    Response.ClearContent();
    Response.ContentType = "text/plain";
    Response.Write(new System.Text.ASCIIEncoding().GetString(formatedBytes));
+2  A: 

While TCP is a stream in concept, the underlying IP sends and receives packets. For the application this means that you always read from socket in a loop, because single "write" by the sender might result in multiple "reads" by the receiver, and the other way around.

This boils down to the fact that it's up to the TCP/IP stack implementation how to split the data you send into packets. The receiving side, again the network stack, does not know how many bytes to expect. It just takes what it got and wakes up the process that waits on that socket, if there's one, or buffers the bytes otherwise.

Your case is easy - just keep reading from the socket until you see the EOF, i.e. zero bytes read. But in general you need an application-level protocol that either defines message lengths, establishes rules for message boundaries, or embeds explicit length information into messages themselves.

Nikolai N Fetissov
I appreciate the additional information - this project has been my first endeavor into Network programming and has been very interesting. I now am receiving the entire data set from .NET and currently working on trying how to maintain the proper order of the data as it comes in. It seems that I receive the packets out of order.
John
Hmm, that is *not possible* with TCP since it maintains sequencing of all sent/received bytes over the *same* connection. I'd blame threading here - are you assuming that if thread was started first then it will send first? That's a broken assumption.
Nikolai N Fetissov
I thought that was the case with TCP - upon closer examination it definitely isn't what is happening either. Threading may be a part of it - I'm going to take a closer look at everything now that I see how the Receive function is behaving and I'll post an update soon. I hope to have this figured out in a little bit.
John
Alright I have everything working now! All my problems came from not understanding the behavior of that Receive function. I'll post my basic solution underneath my question. Thank you again for the help!
John
Glad I could help :)
Nikolai N Fetissov
A: 

//Initialize Byte Buffer Larger than Expected JSON String and Read Bytes byte[] receivedData = new byte[524288]; int numberOfBytes = clientSocket.Receive(receivedData, SocketFlags.None); clientSocket.Close();

Ok, that reads all the bytes that arrive in the buffer. THen closes the stream. Ups.

Read the documentation - for the Receive method. YOu have to repeatedly call it until you get no more data. It will block until SOME data arrives, then return this. It will NOT wait until ALL data has arrived.

TomTom