.NET Socket.Receive()无法从Java SocketServer接收大数据流

4

Java套接字服务器


我有一个Java进程,使用java.io.ServerSocket在TCP套接字上创建侦听器,类似于以下内容(简化):

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

当Java进程接收到请求时,它会启动一个工作线程,然后该工作线程使用java.io.PrintWriter和java.net.Socket发送JSON字符串:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.println("JSON STRING");
out.flush();
out.close();
clientSocket.close();

我已经简化了Java代码,但它本质上就是这样做的。


.NET Socket客户端


接下来,我有一个.NET应用程序,它与托管此Java进程的计算机通信:

//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));

我的问题是,无论出于什么原因,在尝试通过Socket Stream发送稍大的JSON字符串时,此实现都无法正常工作。 对于小数据量(小于2KB),我已经成功地测试了超过100个客户端连接并接收数据而没有任何问题,但是尝试将JSON字符串大小增加到约256KB会导致.NET应用程序截断结果。 增加字节缓冲区数组的大小也没有帮助 - 看起来好像.NET应用程序在传输所有数据之前就断开了连接,或者Java应用程序未使用PrintWriter发送整个字符串。
非常感谢任何对此问题的见解 - 如果我自己取得进展,我会发布任何更新。
这是我得出的解决方案 - 服务器现在运行良好! 再次感谢!
    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个回答

3
虽然TCP在概念上是一个流,但底层的IP发送和接收数据包。对于应用程序来说,这意味着您始终需要在循环中从套接字读取,因为发送方的单个“写入”可能会导致接收方的多个“读取”,反之亦然。
这归结于TCP/IP堆栈实现如何将您发送的数据拆分为数据包。再次提醒,接收端即网络堆栈不知道要期望多少字节。它只接受所得到的字节并唤醒等待该套接字的进程(如果有),否则缓冲字节。
您的情况很简单-只需继续从套接字中读取,直到看到EOF(即读取零字节)。但通常情况下,您需要一个应用级协议,该协议定义消息长度、建立消息边界规则或将显式长度信息嵌入到消息本身中。

我很感激提供的额外信息 - 这个项目是我第一次尝试网络编程,非常有趣。我现在正在从.NET接收整个数据集,并且正在努力尝试如何在数据到达时保持正确的顺序。看起来我收到的数据包是无序的。 - John
哦,使用TCP是不可能的,因为它在同一连接上维护了所有发送/接收字节的排序。我会怀疑线程 - 你是否假设如果线程先启动,那么它就会先发送?这是一个错误的假设。 - Nikolai Fetissov
我曾认为这是TCP的情况 - 经过仔细检查,它明显不是正在发生的事情。线程可能是其中的一部分 - 我现在会仔细查看所有内容,因为我看到接收函数的行为方式,并很快发布更新。我希望很快就能解决这个问题。 - John
好的,现在我已经把所有东西都搞定了!我的所有问题都来自于不理解那个Receive函数的行为。我会在我的问题下面发布我的基本解决方案。再次感谢您的帮助! - John

0
//初始化字节缓冲区,比预期的JSON字符串更大,并读取字节 byte[] receivedData = new byte[524288]; int numberOfBytes = clientSocket.Receive(receivedData, SocketFlags.None); clientSocket.Close();
好的,这将读取缓冲区中到达的所有字节。然后关闭流。糟糕。
阅读接收方法的文档。您必须重复调用它,直到不再获取数据为止。它会阻塞直到有一些数据到达,然后返回此数据。它不会等待所有数据到达。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接