2017-06-10 56 views
3

我使用C#为Windows和Java创建服务器软件来创建客户端软件。 大部分时间都能正常工作,除了那些我不明白的少数例外。TCP发送/接收丢失字节

我通常使用.ReadLine()和.WriteLine()两端进行通信,除非我尝试发送二进制数据。那是我直接写和读字节的时候。 这是软件应该如何工作:

  1. 客户端请求的二进制数据
  2. 服务器响应与二进制数据的长度为
  3. 客户端收到的长度,并将其转换成整数,字符串开始读(长度)字节
  4. 服务器开始写(长度)字节

它工作在大多数情况下,但有时客户端应用程序不会收到完整的数据和b锁。服务器在写入数据后总是立即刷新,所以刷新不是问题。

此外我已经注意到这通常发生在较大的文件,小文件(高达〜1 MB)通常不是问题。

注意似乎C#服务器完全发送数据,所以问题很可能在Java代码的某处。

编辑 - 以下是从客户端

工作的一些日志下载pastebin.com/hFd5TvrF

失败下载pastebin.com/Q3zFWRLB

好像客户在等待2048个字节最后(在这种情况下应该是length - processed = 2048),但由于某种原因客户端阻塞。

任何想法我做错了什么?下面是服务器和客户端的源代码:

C#服务器:

public void Write(BinaryWriter str, byte[] data) 
{ 
    int BUFFER = 2048; 
    int PROCESSED = 0; 
    // WriteString sends the String using a StreamWriter (+ flushing) 
    WriteString(data.Length.ToString()); 
    while (PROCESSED < data.Length) 
    { 
     if (PROCESSED + BUFFER > data.Length) 
      BUFFER = data.Length - PROCESSED; 

     str.Write(data, PROCESSED, BUFFER); 
     str.Flush(); 

     PROCESSED += BUFFER; 
    } 
} 

Java客户端:

public byte[] ReadBytes(int length){ 
    byte[] buffer = new byte[length]; 
    int PROCESSED = 0; 
    int READBUF = 2048; 
    TOTAL = length; 
    progress.setMax(TOTAL); 
    InputStream m; 
    try { 
     m = clientSocket.getInputStream(); 
     while(PROCESSED < length){ 
      if(PROCESSED + READBUF > length) 
       READBUF = length - PROCESSED; 

      try { 
       PROCESSED += m.read(buffer, PROCESSED, READBUF); 
      } catch (IOException e) { 
      } 
      XPROCESSED = PROCESSED; 
     } 
    } catch (IOException e1) { 
     // Removed because of sensitive data 
    } 

    return decryptData(buffer); 
} 
+0

在Java客户端中,当您经历循环时'PROCESSED'的值是多少?我对此感兴趣,因为我很好奇它为什么在读10,000个字节时结束2048个字节。我希望它有1808年阅读上次通过循环,因为它在每次迭代中读取2048字节。 – Poosh

+0

@Poosh 10,000字节是一个例子。我现在不在我的个人电脑上,所以我只能给你估计的价值,我稍后会再次评论准确的价值。 PROCESSED值总是增加1440或2048,最后只增加700。那时候还有2048个字节需要读取,但正如所说的那样,它们不会到达客户端。 – detus

+0

更新:这里有一些日志: 工作下载:https://pastebin.com/hFd5TvrF 未能下载:https://pastebin.com/Q3zFWRLB – detus

回答

0

我已经找到了解决。到目前为止,服务器在发送字节数组后立即发送该长度。出于某种原因,这是行不通的。

所以我已经改变为:

  1. 发送长度,等待客户端与 “OK”
  2. 开始写入字节回应

不知道为什么,但有用。在while(true)循环中运行它,并且它在4分钟内连续发送数据1000次,没有问题,所以我想它是固定的。