Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.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
从TCP C套接字服务器到C#客户端,数据包通过发送连接到一起_C#_C_Sockets_Tcp - Fatal编程技术网

从TCP C套接字服务器到C#客户端,数据包通过发送连接到一起

从TCP C套接字服务器到C#客户端,数据包通过发送连接到一起,c#,c,sockets,tcp,C#,C,Sockets,Tcp,我已经实现了一个C套接字服务器,它是这里示例服务器的一个轻微修改: 它使用的是第一个没有分叉的示例,因为只有一个连接到它。我所做的更改是将bzero和read命令移动到一个单独的函数,然后在main函数中,我将对该单独函数的调用包装在do/while循环中。我还将read命令更改为recv。所以,它看起来像这样,伪代码方面: int main( int argc, char *argv[] ) { ... (code from the sample code I linked to abo

我已经实现了一个C套接字服务器,它是这里示例服务器的一个轻微修改:

它使用的是第一个没有分叉的示例,因为只有一个连接到它。我所做的更改是将bzero和read命令移动到一个单独的函数,然后在main函数中,我将对该单独函数的调用包装在do/while循环中。我还将read命令更改为recv。所以,它看起来像这样,伪代码方面:

int main( int argc, char *argv[] )
{
  ... (code from the sample code I linked to above) ...

  if (newsockfd < 0) {
    perror("ERROR on accept");
    exit(1);
  }

  puts("Connected.");

  do{       
    res = doStuff(newsockfd);   
  } while(res > 0);

  puts("Disconnected.");

  close(newsockfd); 

  ...
}

int doStuff(int socket){
  ...
  int n;
  uint8_t *buf = (uint8_t *) malloc(4);
  uint8_t *packet;

  bzero(buf, 4);
  n = recv(socket, buf, 4, 0);
  if(n<=0) { return(n); }

  (... do stuff, including creating a packet of a certain size ...)

   if (send(socket, packet, packetLength, MSG_DONTWAIT) == -1) {
      puts("Error with send");
      return(-1);
   }
   return(1);
}
intmain(intargc,char*argv[])
{
…(我上面链接的示例代码中的代码)。。。
if(newsockfd<0){
perror(“接受错误”);
出口(1);
}
放置(“已连接”);
做{
res=doStuff(newsockfd);
}而(res>0);
放置(“断开连接”);
关闭(newsockfd);
...
}
int DOSTUF(int插座){
...
int n;
uint8_t*buf=(uint8_t*)malloc(4);
uint8_t*数据包;
b0(buf,4);
n=recv(插座,buf,4,0);
如果(n您必须通过TCP添加到协议中。没有人保证发送的大小与接收的大小匹配。发送的10字节可以作为10乘以1字节接收,发送的10乘以1字节可以作为7字节和3字节接收

向协议中添加帧是很简单的。你可以用一个长度头(每条消息前加一个int,宣布消息长度)老一套地完成这项工作。或者您可以使用,它有许多优点。

您必须通过TCP添加到协议中。没有人保证发送的大小与接收的大小匹配。发送的10字节可以接收为10乘以1字节,发送的10乘以1字节可以接收为7字节和3字节


向协议中添加帧非常简单。您可以老一套地使用长度头(每条消息前有一个int,宣布消息长度)。或者您也可以使用,这有很多优点。

TCP不是特定于数据包的处理的正确选择,它是用于流处理的。要执行应用程序级帧(这是“数据包”概念中的黄鼠狼词语)您需要在客户端上只读取预期大小,处理它,然后读取下一个预期大小,继续。

TCP不是特定于数据包的处理的正确选择,它是用于流处理。要执行应用程序级帧(这是“数据包”概念中的黄鼠狼词语)您需要只读取客户端上的预期大小,对其进行处理,然后读取下一个预期大小,然后继续。

您看到的问题是TCP的预期行为。TCP试图在传输时尽可能高效,因此它将收集多个写入数据到单个数据包中,以便尽可能地进行传输

您显然还没有看到(但在某些时候会看到)的问题是碎片问题。当您试图发送超过最大传输单位(MTU)的数据时,就会出现碎片问题单次写入时的大小。例如,如果您写入2000字节,MTU大小为1500,则接收端将获得一个1500字节的数据包,然后是一个500字节的数据包


这个故事的寓意是,接收者必须准备好通过多次读取和从一次读取中提取多条消息来重建消息。为此,您需要实现一个协议,允许您从字节流中提取单个消息。

您看到的问题是TCP试图在传输时尽可能高效,因此它将收集多个写操作到一个数据包中,以便在任何可能的情况下进行传输

您显然还没有看到(但在某些时候会看到)的问题是碎片问题。当您试图发送超过最大传输单位(MTU)的数据时,就会出现碎片问题单次写入时的大小。例如,如果您写入2000字节,MTU大小为1500,则接收端将获得一个1500字节的数据包,然后是一个500字节的数据包


这个故事的寓意是,接收者必须准备好通过多次读取和从一次读取中提取多条消息来重建消息。为此,您需要实现一个协议,允许您从字节流中提取单个消息。

仔细阅读recv()/send()的文档并了解这两个函数接收/发送的字节数不一定像它们被告知的那么多,但很少。因此,循环此类调用直到接收/发送所有预期数据是一个好主意,更不用说是必要的。仔细阅读recv()/send()的文档并了解到这两个函数接收/发送的字节数不一定像它们被告知的那么多,但很少。因此,循环此类调用直到所有预期数据都已接收/发送是一个好主意,更不用说是必要的。感谢您的建议。我永远不会在一次发送中发送超过~600字节()命令,通过以太网(具有MTU 1500字节)。你认为我还需要担心碎片吗?理论上,是的。实际上,可能不是。但是,最好是按照理论编写代码,特别是如果你希望你的代码被广泛部署,或者如果你希望你的代码需要长时间维护。TCP不会对数据包进行碎片化。它使用MTU发现找到最大数据包大小并发送适合的数据包。有时数据包会被碎片化,但这不是TCP的错误。由于TCP是基于流的,不基于数据包,并且不需要保持原始数据包大小,因此它会将其流切割成适合无碎片的大小。感谢您的建议。我发送的数据包不会超过~6个通过以太网(MTU为1500字节)在单个send()命令中输入00字节。您认为我还需要担心碎片问题吗?理论上,是的。实际上,可能不是。但是,编写理论代码总是最好的,尤其是当您希望代码被广泛部署时,或者如果您希望这样做的话