【问题标题】:TCP communication between C# and Java serversC# 和 Java 服务器之间的 TCP 通信
【发布时间】:2019-04-15 10:22:37
【问题描述】:

我正在尝试使用 TCP 将 json 从 C# 服务器传递到 Java 服务器,问题是 Java 服务器第一次似乎接收到一个空的 json。第二次及以后它工作正常,请参阅下面的输出。欢迎任何想法或建议,在此先感谢。

输出:

Starting server...
Waiting for a connection..
Connected!
Reading...
Received empty object
Received: 
Connected!
Reading...
Received: "Request:gethotellist"
Connected!
Reading...
Received: "Request:gethotellist"

这里是发送json的C#代码sn-p:

public void GetHotelList()
{
TcpClient clientSocket = new TcpClient();
clientSocket.Connect("127.0.0.1", 6767);

NetworkStream ns = clientSocket.GetStream();

string jsonRequest = "Request:gethotellist";

string jsonToSend = JsonConvert.SerializeObject(jsonRequest);

byte[] dataBytes = Encoding.UTF8.GetBytes(jsonToSend);

ns.Write(dataBytes, 0, dataBytes.Length);

ns.Close();
}

Java 服务器:

public class JHotelServer
{

public static void main(String[] args) throws IOException
{
  final int PORT = 6767;

  System.out.println("Starting server...");     

  @SuppressWarnings("resource")
  ServerSocket welcomeSocket = new ServerSocket(PORT);  

  System.out.println("Waiting for a connection..");

  while(true)
  {             
     try
     {
        Socket connectionSocket = welcomeSocket.accept();  

        System.out.println("Connected!");

        Thread connectionThread = new Thread(new TcpConnectionManager(connectionSocket));
        connectionThread.start();
     }

     catch(IOException ioe)
     {
        ioe.printStackTrace();
     }         
  }
}
}

这里是 Tcp 通信管理器:

public class TcpConnectionManager implements Runnable
{   
private DataInputStream inFromDotNet;

public TcpConnectionManager(Socket socket) throws IOException
{
  inFromDotNet = new DataInputStream(socket.getInputStream());
}

@Override
public void run()
{
  try
  {               
     System.out.println("Reading...");

     byte[] rvdMsgByte = new byte[inFromDotNet.available()];

     // Collecting data into byte array
     for (int i = 0; i < rvdMsgByte.length; i++)
     {
         rvdMsgByte[i] = inFromDotNet.readByte();
     }

     if (rvdMsgByte.length == 0)
     {
        System.out.println("Received empty object");
     }

     // Converting collected data in byte array into String.
     String rvdMsgTxt = new String(rvdMsgByte);

     System.out.println("Received: " + rvdMsgTxt);       
  }

  catch(IOException ioe)
  {
     ioe.printStackTrace();
  }
}
}

【问题讨论】:

    标签: java c# json tcp


    【解决方案1】:

    根据显示的代码,完全可以预期有时会得到一个空负载,因为如果负载数据包尚未到达:inFromDotNet.available() 将为零。

    基本上,.available()(和等价物)应该从不用于确定有关内容的任何内容,除了“当前缓冲的字节数”(可能在同步读取和异步读取之间进行选择) .

    这里常用的方法有两种:

    • 使用 EOF 表示有效负载的结束,即读取 直到套接字说它已关闭并且所有内容都已读取;如何检测这取决于特定的套接字 API(例如,在 .NET 中,当Receive 返回一个非正数时)
    • 实现某种基本的成帧协议

    如果每个套接字只发送一条消息,则第一个选项是相关的;如果您将在每个套接字上发送多条消息,则第二个选项是必要的。一个基本的框架协议可以像“消息由换行符分隔”一样简单,但在许多情况下,您可能需要二进制安全的框架,例如长度前缀。例如,您的 JSON 可能包含换行符,这可能会被错误地解释为帧的结尾。

    在任何一种情况下:对于套接字,您几乎总是需要循环读取,因为数据可以拆分为多个数据包,和/或您的接收缓冲区大小可能太小。所以通常情况下,您会循环和缓冲所有有效负载,直到检测到 EOF 或帧结束,然后然后开始尝试处理内容。特别是,您通常不应该尝试解码文本,直到您知道您拥有整个内容,因为多字节字符可能跨越多个“读取”/“接收”调用,所以:除非您使用有状态文本解码器,否则您可能会错误地解码此类字符。

    您所看到的行为几乎适用于所有平台和语言;它并不特定于 Java/C#。

    【讨论】:

      猜你喜欢
      • 2014-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-22
      • 1970-01-01
      相关资源
      最近更新 更多