代码之家  ›  专栏  ›  技术社区  ›  John

没有从Java SockServer接收大数据流

  •  4
  • John  · 技术社区  · 14 年前

    Java套接字服务器


    我有一个Java进程,它使用JavaIO.Servocket之类的东西(TCP)在TCP套接字上创建监听器(简化):

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

    JAVA进程在接收请求时启动工作线程,然后工作人员使用JavaIO.PrimTrrIt和JavaNET.SoCult发送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应用程序没有使用这个字符串发送整个字符串。

    任何对这个问题的了解都会非常感谢-如果我自己有任何进展,我会发布任何更新。


    这是我找到的解决方案-服务器现在工作得很好!再次感谢!


        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 回复  |  直到 14 年前
        1
  •  3
  •   Nikolai Fetissov    14 年前

    当TCP是 流动 在概念上,底层IP发送和接收 小包 . 对于应用程序,这意味着 总是 从插座读取 在一个循环中 因为发送方的单个“写入”可能会导致接收方多次“读取”,反之亦然。

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

    你的箱子很容易-一直从插座上读直到你看到 EOF ,即读取零字节。但一般来说,您需要一个应用程序级的协议,它要么定义消息长度,为消息边界建立规则,要么将显式的长度信息嵌入到消息本身中。

        2
  •  0
  •   TomTom    14 年前

    //初始化大于 应为JSON字符串和读取字节 byte[]receivedData=新建 字节[524288];int numberofbytes= clientsocket.receive(接收数据, socketflags.none); clientsocket.close();

    好的,它读取到达缓冲区的所有字节。然后关闭流。不间断电源。

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