2016-04-19 53 views
0

TCP是基于流的协议。为了将该流转换为我的消息,我将每条消息的大小与消息本身一起发送。在服务器端,我首先读取具有大小的消息的前两个字节。然后我创建一个字节数组,其大小等于刚才读取的大小。然后我读入该数组中的字节。但由于某些原因,正在读取的字节数多于指定的字节数。我怎样才能读取与我指定的完全相同的字节数?套接字编程:如何从缓冲区读取指定数量的字节?

这里是我的代码:

while (true) 
{ 
    data = null; 
    length = null; 

    size = new byte[2]; 

    handler.Receive(size); 

    length += Encoding.ASCII.GetString(size, 0, 2); 
    System.Console.WriteLine("Size: " + Int32.Parse(length)); 

    bufferSize = Int32.Parse(length) + 2; 
    bytes = new byte[bufferSize]; 

    handler.Receive(bytes); 

    data += Encoding.ASCII.GetString(bytes, 0, bufferSize); 
    System.Console.WriteLine("Data: " + data); 
} 

这是我的服务器在Windows PC上运行,用C#编写。我的客户端运行在用Java编写的android手机上。

+1

一)你使用为什么''长度+ = ...' '而不是''长度= ...''? b)为什么bufferSize = Int32.Parse(length)+ 2;''中的''+ 2''? c)你期望的长度是2个ASCII字符。客户端是否以2字节的形式发送它们?或者可能是一个4字节的整数? – f1sh

+0

a)我猜'length + = ...'和'length = ...'是一样的,因为每次都将length设置为null。 b)处理客户端发送的换行符。 –

+0

'length'必须是'int'而不是'string'。也许你来自'python'或'javascript'世界。 – i486

回答

1

它为什么要添加两到一个已经发送的大小不清楚 - 你已经占了两个额外的字节中存储长度你以前收到的。所以我会摆脱+2

您还需要尊重已经在您的问题中陈述的事实 - TCP是一个字节序列,而不是消息。因此,您无法保证Receive的呼叫是要检索整个“消息”还是只是部分(或多个消息的可能部分)消息。因此,您需要确保您遵守Receive返回值

我们也许可以重新编写代码为:

while (true) 
{ 
    data = null; 
    length = null; 

    size = ReceiveExactly(handler,2); 

    length = Encoding.ASCII.GetString(size, 0, 2); //Why +=? 
    bufferSize = Int32.Parse(length); //Why + 2? 
    System.Console.WriteLine("Size: " + bufferSize); 

    bytes = ReceiveExactly(handler,bufferSize); 

    data += Encoding.ASCII.GetString(bytes, 0, bufferSize); 
    System.Console.WriteLine("Data: " + data); 
} 

ReceiveExactly的定义是这样的:

private byte[] ReceiveExactly(Socket handler, int length) 
{ 
    var buffer = new byte[length]; 
    var receivedLength = 0; 
    while(receivedLength < length) 
    { 
     var nextLength = handler.Receive(buffer,receivedLength,length-receivedLength); 
     if(nextLength==0) 
     { 
     //Throw an exception? Something else? 
     //The socket's never going to receive more data 
     } 
     receivedLength += nextLength; 
    } 
    return buffer; 
} 
2

的字节使用的方法

Socket.Receive(Byte[], Int32, Int32, SocketFlags) 

而非Socket.Receive(Byte[])接收特定量。见规格表here

我怀疑你想要的东西像

int len = Socket.Receive(bytes, 0, bufferSize, SocketFlags.None); 

data += Encoding.ASCII.GetString(bytes, 0, len); 
System.Console.WriteLine("Data: " + data); 
+0

前两个字节将具有原始消息的其余部分的大小。我将这些字节转换为字符串,然后将其解析为int。然后我创建一个这么大的缓冲区,以便在下一次接收呼叫时读取原始消息。 –

+0

您的解决方案对我无效。 –

相关问题