Socket with C# and java

Asked

Viewed 517 times

2

Good morning, I am writing an application where the server socket is in C#(due there are some drivers have to be in c#) and the client in Java. I can make the communication perfectly between them, but when passing data, I have the following mistake:

System.Argued tofrangeexception: Argument specified was outside the range of valid values. Name of the parameter: size in System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) in tests.handleClinet.doChat() in d: c# socket tests handleClinet.Cs:line 40

Server code c#:

//Class to handle each client request separatly
public class handleClinet
{
    TcpClient clientSocket;
    string clNo;
    public void startClient(TcpClient inClientSocket, string clineNo)
    {
        this.clientSocket = inClientSocket;
        this.clNo = clineNo;
        Thread ctThread = new Thread(doChat);
        ctThread.Start();
    }
    private void doChat()
    {
        int requestCount = 0;
        byte[] bytesFrom = new byte[10000];
        string dataFromClient = null;
        Byte[] sendBytes = null;
        string serverResponse = null;
        string rCount = null;
        requestCount = 0;
        while ((true))
    {
        try
        {
            requestCount = requestCount + 1;
            NetworkStream networkStream = clientSocket.GetStream();
            Console.WriteLine(" >> " + (int)clientSocket.ReceiveBufferSize);
            networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
            dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
            dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
            Console.WriteLine(" >> " + "From client-" + clNo + dataFromClient);

            rCount = Convert.ToString(requestCount);
            serverResponse = "Server to clinet(" + clNo + ") " + rCount;
            sendBytes = Encoding.ASCII.GetBytes(serverResponse);
            networkStream.Write(sendBytes, 0, sendBytes.Length);
            networkStream.Flush();
            Console.WriteLine(" >> " + serverResponse);
        }
        catch (Exception ex)
        {
            Console.WriteLine(" >> " + ex.ToString());
            return;
        }
    }
}

}

Client Code: Java

public static void main(String[] args) throws IOException {

      String sentence;
      String modifiedSentence;
      BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
      Socket clientSocket = new Socket("localhost", 9999);
      DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
      BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
      sentence = inFromUser.readLine();
      outToServer.writeBytes(sentence + '\n');
      modifiedSentence = inFromServer.readLine();
      System.out.println("FROM SERVER: " + modifiedSentence);
      clientSocket.close();
}

New client in Java:

public class Cliente {

    public static void main(String[] args) {

        try {
            Socket s = new Socket("127.0.0.1", 9999);
            InputStream i = s.getInputStream();
            OutputStream o = s.getOutputStream();
            String str;
            while(true){
                byte[] line = new byte[100];
                System.in.read(line);
                o.write(line);
                i.read(line);
                str = new String(line);
                System.out.println(str.trim());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

Grateful for the help.

1 answer

2


Substitute:

networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);

For:

int read = networkStream.Read(bytesFrom, 0, bytesFrom.Length);

Substitute:

dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);

For:

dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom, 0 , read);

And still put all the content after int read = in a if, thus:

if ( read > 0 )
{
    ...
}

The explanation

.ReceiveBufferSize tells the available buffer size, not how much data has on it. The method, in this case is .Available. In fact, I suggest trading the first for the other.

The problem in the first row replaced is that .ReceiveBufferSize may be much larger than bytesFrom.Length, what gives this mistake. .Read expects you to spend as much as you can read, and the most you can read is the size of bytesFrom, not the size of the socket buffer.

'Cause it’s important to see the return de . Read, because you don’t know how many bytes were actually read. You can’t trust .Available, has to take the same return. From this already follows the justification of the second substitution. The way it was, you were always creating a string of 10,000 chars, even if you only received one byte.

The if is not important as long as it is guaranteed that the socket is blocking. But if there is no guarantee, then the if is needed by a .Read can return after having read zero bytes, which gives error in several of the functions called subsequently.

  • Very good, solved the problem. I did some tests simulating the real environment, where I will have a client side request of a specific ID, from this request, the serverSocket will monitor an equipment and return its value in real time (around 250ms). I put a for to simulate as a counter and he did all the operation, but the client (Java) did not recognize and need to interact manually. Could the client read the response as it is generated from the server? I made a change to the client, I will post the new code. Thanks for the help.

  • That is already another question, but the answer is yes, it has as the customer read the answer as soon as it arrives. Study about "Blocking vs. non-blocking sockets". Blocking hangs . Read if you have nothing, non-bloking does not lock and returns zero. Your new Java client has the same problems as C#. You are not saving or testing the return. read(), so you don’t know how many bytes were read.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.