试图理解网络通信背后的逻辑

时间:2014-03-10 15:02:52

标签: c networking

在C中,接收/发送您通常做的数据(大致):

服务器:

  • 创建套接字
  • 将套接字绑定到端口
  • 接受
  • 接收发送数据

在客户端:

  • 创建套接字
  • 连接
  • 接收发送

我的问题来自服务器完成后的 accept

想象一下,在服务器端 accept之后有三条单独的行 发送数据:

connfd = accept(listenfd, (struct sockaddr*)NULL ,NULL);
write(connfd, var1, var1Size);
write(connfd, var2, var2Size);
write(connfd, var3, var3Size);

这是否意味着在客户端我需要三次读取? 像这样:

read(sockfd, &x, size1);
read(sockfd, &y, size2);
read(sockfd, &z, size3);

换句话说,发送和接收呼叫应该如何对应 在服务器端和客户端?每个发送应该是客户端的相应接收吗?

如果在客户端,经过3次读取调用(如上所述)后,我想将数据发送到服务器怎么办? 我可以分别在客户端和服务器端添加一个新发送和一个新接收吗?

所有这些发送/接收是否应在单个accept呼叫上下文中发生?

这是一张图片,可以更好地说明我可能感兴趣的场景:

enter image description here

欢迎使用伪代码解释如何处理这种连接。

2 个答案:

答案 0 :(得分:3)

除非您使用的是具有“消息”概念的协议,例如UDP,你所拥有的只是一个字节流。您可以按照自己的意愿发送和接收它们。

例如,您可以发送两个16位整数并将它们作为一个32位整数接收。这可能不是你想要的,但它完全合法,并且在需要 的情况下一直使用。只要对您的应用程序有意义,您就可以独立地组合数据结构(发送和接收)。

您的字节按write()的顺序发送,您将以相同的顺序接收它们。即。

send(var1)  --->  recv(var1)
send(var2)  --->  recv(var2)

var2之前,您将收到var1正常TCP中的 no 方式(禁止未使用的边缘情况,我甚至都没有指定,因为没有人应该使用它们)

TCP通信是双向的:每个端点(客户端和服务器)可以同时发送。由您和您的应用程序决定何时发送以及何时接收。发送和接收缓冲区是独立的:你可以发送几个字节,接收一些,发送更多......并且它们之间不会有任何干扰(即你不会通过发送一些数据而不是“覆盖”接收缓冲区亦然)。

我将再次重复:TCP中的所有内容都是字节流。 TCP不知道也不关心这些字节是如何构造的,无论是在发送方还是在接收方。它是 ALL 由您决定。发送整数或数据结构时,您将发送内存转储 as bytes

例如,在尝试send()数据结构时会出现一个常见错误,并且由于发送缓冲区已满,系统将进行部分写入。如果您没有检查send()调用的返回状态以检测这种情况,然后自己发送剩余的字节 ,则在另一个send()调用中,您的客户端将是如果你指定了MSG_WAITALL,那么当它需要完整的结构并且只接收其中的一部分时,它会被卡在recv()中。

答案 1 :(得分:0)

  1. TCP是一种流协议,在接收方,您无法确定调用该发送的次数。每当调用recv时,它将给出要读取的字节数,如果请求的字节数不可用,则它将返回当前在套接字缓冲区中的字节数。

  2. 如果是UDP,它会像你提到的那样工作,它是一个数据报协议。 (使用recvfrom来恢复数据)