简体   繁体   中英

Java Server, C# Client. Sending Data

So, I'm having a problem with sending data from a C# client to a Java Server. The connection is going through, however I'm messing something up somewhere I guess.

Here's the ServerSided Code

package com.chris.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;


public class Server implements Runnable
{
    private String serverName;
    private boolean isRunning;

private ServerSocket serverSocket;
private Socket clientSocket;

public Server(String name, int port)
{
    try 
    {
        this.serverName = name;
        this.serverSocket = new ServerSocket(port);
        this.isRunning = true;
        new Thread(this).start();
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    }
}

private BufferedReader recv;

public void run()
{
    while(isRunning)
    {
        try 
        {
            clientSocket = serverSocket.accept();
            System.out.println("Client Connected from " + clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort());

            recv = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

            System.out.println("Data Recieved: " + recv.readLine());

            clientSocket.close();
        }
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }
}
}

Here is the Client Code

lass TCPClient
{
    private TcpClient Client;
    private NetworkStream Stream;

    private Byte[] Data;

    public TCPClient(string address, int port)
    {
        Client = new TcpClient();
        Client.Connect(address, port);

        Stream = Client.GetStream();

        SendData("Test Data");

        while (Client.Connected)
        {

        }
    }

    public void SendData(string message)
    {
        Data = System.Text.Encoding.ASCII.GetBytes(message);
        Stream.Write(Data, 0, Data.Length);

        Console.WriteLine("Sent: {0}", message);
    }
}

The server registers the connection, and the client seems to think that it has sent the data, however I can't tell if it's the Client not sending the Data or if it's the Server not receiving it. Considering the Console.Writeline is just printing out the message that was converted into bytes, I can't tell.

If you want to work with JSON, refer to this excellent article on getting Java to send message serializing your java type to JSON and on receiving C# to Deserealize to a C# type.

Excerpt in Java:

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import com.google.gson.Gson;

public class GuyServer {
 public static void main(String[] args)
 throws IOException {
      Gson gson = new Gson();
      ServerSocket serverSocket = new ServerSocket(16001);
      System.out.println("Listening on port 16001. " 
              + "Press enter to quit "
              + "after the next connection.");
      while (System.in.available() == 0) {
           Socket socket = serverSocket.accept();
           System.out.println("A client has connected." 
               + " Sending a new Guy down the pipe.");
           PrintWriter out =
               new PrintWriter(socket.getOutputStream(),
                   true);
           Guy guy = Guy.getRandomGuy();
           String json = gson.toJson(guy);
           out.print(json);
           out.close();
           socket.close();
       }
      System.out.println("Quitting...");
      serverSocket.close();
  }
}

C# End:

using System;
using System.IO;
using System.Net.Sockets;
using System.Web.Script.Serialization;

class GuyClient
{
     static void Main(string[] args)
     {
          String input;

          using (TcpClient tcpClient = 
                  new TcpClient("localhost", 16001))
          using (NetworkStream networkStream = 
                  tcpClient.GetStream())
          using (StreamReader streamReader = 
                  new StreamReader(networkStream))
          {
               input = streamReader.ReadToEnd();
           }

          Console.WriteLine("Received data: " + input + "\n");

          JavaScriptSerializer javaScriptSerializer = 
                  new JavaScriptSerializer();
          Guy bob = javaScriptSerializer
                  .Deserialize<Guy>(input) as Guy;
          Console.WriteLine(bob.ToString());
      }
}

Java Class

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Guy {
     private String name;
     public String getName() {
          return name;
      }     
 }

}

C# Serlizable class

using System;
using System.Collections.Generic;

[Serializable]
class Guy
{
     public string Name { get; set; }    
}

I cleaned this up a bit to make it easier to understand. It won't compile but you get the idea.

Java TCP client: you should use DataInputStream and DataOutputStream separately to send and receive data:

try
                    {
                        mOutStream = new DataOutputStream(mClientSocket.getOutputStream());
                        mInStream = new DataInputStream(mClientSocket.getInputStream());
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }

Example of manipulating the output data stream (send out):

public static void WriteString(DataOutputStream os, String value) throws IOException {
        if (value!=null) {
            byte[] array = value.getBytes(CHARSET);
            WriteBuffer(os,array);
        } else {
            WriteInt(os,0);
        }
    }

public static void WriteBuffer(DataOutputStream os, byte[] array) throws IOException {
        if ((array!=null) && (array.length > 0) && (array.length <= MAX_BUFFER_SIZE)) {
            WriteInt(os,array.length);
            os.write(array);
            //os.flush();
        } else {
            WriteInt(os,0);
        }
    }

public static void WriteInt(DataOutputStream os, int value) throws IOException {
        byte[] intAsBytes = ConvertIntToBytes(value);
        os.write(intAsBytes);
        //os.flush();
    }

Example of using Input stream (receive):

public static String ReadString(DataInputStream is) throws IOException {
        String ret=null;
        int len = ReadInt(is);
        if ((len == 0) || (len > MAX_BUFFER_SIZE)) {
            ret = "";
        } else {
            byte[] buffer = new byte[len];
            is.readFully(buffer, 0, len);
            ret = new String(buffer, CHARSET);
        }
        return (ret);
    }

public static int ReadInt(DataInputStream is) throws IOException {
        int ret=0;
        byte[] intAsBytes = new byte[4];
        // this will just block forever...
        is.readFully(intAsBytes);
        ret = ConvertBytesToInt(intAsBytes);
        return (ret);
    }

public static int ConvertBytesToInt( byte[] array) {
        int rv = 0;
        for ( int x = 3; x >= 0; x-- )
        {
            long bv = array[ x ];
            if ( x < 3 & bv < 0 ) // keeping the sign intact???
                bv +=256;
            //rv *= 256;
            rv = rv << 8;
            rv += bv;
        }
        return rv;
    }

C# TCP Client: (this updates the 1st answer), noted that in C# using BinaryWriter is similar to DataOutputStream in Java:

Define your const of MAX_BUFFER_SIZE=1024 (example) somewhere in your code!

public static void WriteString(BinaryWriter os, string value)  {
            if (value!=null) {
                byte[] array = System.Text.Encoding.Unicode.GetBytes(value);
                WriteBuffer(os,array);
            } else {
                WriteInt(os,0);
            }
        }

public static void WriteBuffer(BinaryWriter os, byte[] array) {
            if ((array!=null) && (array.Length > 0) && (array.Length < MAX_BUFFER_SIZE)) {
                WriteInt(os,array.Length);
                os.Write(array);
            } else {
                WriteInt(os,0);
            }
        }

public static void WriteInt(BinaryWriter outStream, int value)  {
            byte[] buffer = BitConverter.GetBytes(value);
            //  Array.Reverse(buffer);
            outStream.Write(buffer);
        }

What worked for me: I had to append a byte equal to 0 to my send buffer.

Excerpt from IBM:

The end-of-message marker technique:

A third technique most often seen in C programs is to send a null-terminated string. A null-terminated string is a string of bytes terminated by a byte of binary 0.

Other excerpt:

How read() handles zero-byte STREAMS messages is determined by the current read mode setting. In byte-stream mode, read() accepts data until it has read N bytes, or until there is no more data to read, or until a zero-byte message block is encountered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM