【问题标题】:.NET Socket.Receive() Not Receiving Large Data Streams from Java SocketServer.NET Socket.Receive() 未从 Java SocketServer 接收大数据流
【发布时间】:2010-10-29 02:47:21
【问题描述】:

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 套接字客户端


接下来我有一个 .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));

我的问题是,无论出于何种原因,当我尝试通过套接字流发送稍大的 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));

【问题讨论】:

    标签: c# java .net sockets


    【解决方案1】:

    虽然 TCP 在概念上是一个,但底层 IP 发送和接收 数据包。对于应用程序,这意味着您总是从套接字读取循环,因为发送方的一次“写入”可能会导致接收方多次“读取”,而其他方式。

    这归结为这样一个事实,即如何将您发送的数据拆分为数据包取决于 TCP/IP 堆栈实现。接收方,同样是网络堆栈,不知道需要多少字节。它只是获取它得到的内容并唤醒等待该套接字的进程(如果有的话),否则缓冲字节。

    您的情况很简单 - 只需继续从套接字读取,直到看到 EOF,即读取零字节。但一般来说,您需要一个应用程序级协议来定义消息长度、建立消息边界规则或将显式长度信息嵌入消息本身。

    【讨论】:

    • 感谢您提供的额外信息 - 这个项目是我第一次尝试网络编程,非常有趣。我现在正在从 .NET 接收整个数据集,目前正在尝试如何在数据传入时保持正确的顺序。看来我收到的数据包是乱序的。
    • 嗯,这对于 TCP 来说是不可能的,因为它维护了所有通过 same 连接发送/接收字节的顺序。我会在这里责怪线程-您是否假设如果线程首先启动,那么它将首先发送?这是一个错误的假设。
    • 我认为 TCP 就是这种情况 - 经过仔细检查,它肯定也不是正在发生的事情。线程可能是其中的一部分 - 现在我将仔细研究所有内容,因为我看到了 Receive 函数的行为,并且我将很快发布更新。我希望尽快解决这个问题。
    • 好的,我现在一切正常!我所有的问题都来自于不理解 Receive 函数的行为。我将在我的问题下方发布我的基本解决方案。再次感谢您的帮助!
    【解决方案2】:

    //初始化大于的字节缓冲区 预期的 JSON 字符串和读取字节 byte[] receivedData = new 字节[524288]; int numberOfBytes = clientSocket.Receive(receivedData, SocketFlags.None); clientSocket.Close();

    好的,它读取到达缓冲区的所有字节。然后关闭流。起起伏伏。

    阅读文档 - 了解 Receive 方法。你必须反复调用它,直到你没有更多的数据。它将阻塞直到一些数据到达,然后返回这个。它不会等到所有数据都到达。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-31
      • 1970-01-01
      • 2015-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      相关资源
      最近更新 更多