Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 套接字编程:如何从缓冲区读取指定数量的字节?_C#_Sockets - Fatal编程技术网

C# 套接字编程:如何从缓冲区读取指定数量的字节?

C# 套接字编程:如何从缓冲区读取指定数量的字节?,c#,sockets,C#,Sockets,TCP是基于流的协议。要将该流转换为我的消息,我将每个消息的大小与消息本身一起发送。在服务器端,我首先读取消息的前两个字节,其大小为。然后我创建一个字节数组,大小等于刚刚读取的大小。然后我将字节读入该数组。但由于某些原因,正在读取的字节数超过了指定的字节数。如何读取与指定的字节数完全相同的字节数 这是我的密码: while (true) { data = null; length = null; size = new byte[2]; handler.Rece

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手机上。

要接收特定数量的字节,请使用该方法

Socket.Receive(Byte[], Int32, Int32, SocketFlags)
而不是
Socket.Receive(字节[])
。参见规格

我猜你想要像这样的东西

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

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

要接收特定数量的字节,请使用

Socket.Receive(Byte[], Int32, Int32, SocketFlags)
而不是
Socket.Receive(字节[])
。参见规格

我猜你想要像这样的东西

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

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

现在还不清楚为什么要在传输的大小上增加两个字节——您已经考虑了在上次接收期间存储长度的两个额外字节。所以我要去掉
+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;
}
private byte[]receivejustice(套接字处理程序,int-length)
{
var buffer=新字节[长度];
var receivedLength=0;
while(接收长度<长度)
{
var nextLength=handler.Receive(缓冲区、接收长度、接收长度);
如果(nextLength==0)
{
//抛出一个异常?其他什么?
//套接字永远不会接收更多的数据
}
接收长度+=下一个长度;
}
返回缓冲区;
}

不清楚您为什么要在已传输的大小上添加两个字节-您已经考虑了在上次接收期间存储长度的两个额外字节。所以我要去掉
+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;
}
private byte[]receivejustice(套接字处理程序,int-length)
{
var buffer=新字节[长度];
var receivedLength=0;
while(接收长度<长度)
{
var nextLength=handler.Receive(缓冲区、接收长度、接收长度);
如果(nextLength==0)
{
//抛出一个异常?其他什么?
//套接字永远不会接收更多的数据
}
接收长度+=下一个长度;
}
返回缓冲区;
}

a)为什么使用
length+=…
而不是
length=…
?b) 为什么
bufferSize=Int32.Parse(length)+2中的
+2
?c) 您希望长度为2个ascii字符。客户端是否以2字节的形式发送它们?或者可能是一个4字节的整数?a)我猜
length+=…
length=…
相同,因为每次length都被设置为null。b) 它用于处理从客户端发送的换行符。
length
必须是
int
而不是
string
。也许你来自
python
javascript
世界。
length
string
。在使用as
int
之前,我将其解析为
int
。为什么在这里使用字符串?为什么不直接使用
BitConverter
将长度转换为字节[]
?以ASCII格式发送长度意味着每条消息最多只能发送99字节。从理论上讲,这两个字节可以对最大为65535字节的消息进行编码。a)为什么要使用
length+=…
而不是
length=…
?b) 为什么
bufferSize=Int32.Parse(length)+2中的
+2
?c) 您希望长度为2个ascii字符。客户端是否以2字节的形式发送它们?或者可能是一个4字节的整数?a)我猜
length+=…
length=…
相同,因为每次length都被设置为null。b) 它用于处理从客户端发送的换行符。
length
必须是
int
而不是
string
。也许你来自
python
javascript
世界。
length
string
。在使用as
int
之前,我将其解析为
int
。为什么在这里使用字符串?为什么不直接使用
BitConverter
将长度转换为字节[]
?以ASCII格式发送长度意味着每条消息最多只能发送99字节。从理论上讲,这两个字节可以对最大为65535字节的消息进行编码。前两个字节的大小与原始消息的其余部分相同。我将这些字节转换为字符串,然后将其解析为int。然后我创建一个如此大的缓冲区,以便在下一个接收调用中读取原始消息。前两个字节的大小与原始消息的其余部分相同。我将这些字节转换为字符串,然后将其解析为int。然后我创建一个如此大的缓冲区,以便在下一个接收调用中读取原始消息。