gpt4 book ai didi

java - C# 和 Java 服务器之间的 TCP 通信

转载 作者:可可西里 更新时间:2023-11-01 02:33:27 25 4
gpt4 key购买 nike

我正在尝试使用 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#代码片段:

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();
}
}
}

最佳答案

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

基本上,除了“当前有字节缓冲”(可能是为了在同步读取和异步读取之间进行选择)。

这里常用的方法有两种:

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

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

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

您看到的行为对于几乎所有平台和语言都是常见的;它不特定于 Java/C#。

关于java - C# 和 Java 服务器之间的 TCP 通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53266539/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com