c - 仍然使用 TCP_NODELAY 发送一条消息

标签 c sockets tcp

根据我对 Nagel 算法的理解,如果可能的话,它会尝试在一条消息中发送多条消息,以使用更少的带宽。

我的问题是,对于一个大学项目,我必须禁用它;我必须首先发送一个名称,然后发送年、月、日,最后发送文件名。

在服务器端,我必须将其处理为字符串:名称/年/月/日/文件名

明确指出我的客户端/服务器应该与其他学生的客户端/服务器一起工作。因此,我不允许在每条消息的末尾设置\0 或其他字符,然后在服务器上处理它,因为任何学生都可能有不同的结束字符。

我的代码如下所示

int main(int argc, char *argv[])
{
  int sockfd;
  int yes=1;
  struct sockaddr_in their_addr;
  struct hostent *he;
  if ((he=gethostbyname(argv[1])) == NULL) {
    perror("Client: gethostbyname");
    return EXIT_FAILURE;
  }

  if ((sockfd = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1) {
    perror("Client: socket");
    return EXIT_FAILURE;
  }

  their_addr.sin_family = AF_INET;
  their_addr.sin_port = htons(PORT);
  their_addr.sin_addr = *((struct in_addr*)he->h_addr);
  memset(&(their_addr.sin_zero), '\0', 8);

  if (connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr))==-1) {
    perror("Client: connect");
    return EXIT_FAILURE;
  }

  if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(int))==-1) {
    perror("Client: setsockopt");
    return EXIT_FAILURE;
  }
  if (send(sockfd,argv[2],strlen(argv[2]),0)==-1) {
    perror("Client: send username");
    return EXIT_FAILURE;
  }

  if (send(sockfd,argv[4],4,0)==-1) {
    perror("Client: send year");
    return EXIT_FAILURE;
  }

我认为这会起作用,因为这条线

setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(int)

有时也这样写(反正都不起作用)

setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &yes, sizeof(yes));

我没有找到任何说明应该这样做的内容(我总是使用 0 而不是 IPPROTO_TCP):

sockfd = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

但是我发现了一些这样的代码,所以我尝试了一下,但它仍然不起作用。 在服务器端,我也有非常标准的代码,包含5个recv(),我也尝试在那里实现TCP_NODELAY,但它仍然不起作用。我怀疑服务器代码是否有帮助,因为问题似乎来自客户端发送一条消息。

所以我想知道我做错了什么以及如何有效地获取 5 条不同的消息而不是一条(我目前正在做的是在每次发送之间进行 sleep(1) ,这显然不是最佳的)。

提前感谢您的回复

最佳答案

TCP 中没有端到端的“消息”;它是一个字节流协议(protocol)。该协议(protocol)可以根据需要自由组合来自多个发送的字节,或者将一个发送分成多个段。这意味着如果你想要离散的消息,那么你必须发明它们。通常的方法包括在实际消息字节之前发送一个长度;或具有特定的终止字符(接收者必须扫描该字符);或使用固定长度的消息(我建议不要这样做,因为它不灵活)。

所有这些都需要建立一个供所有学生使用的标准方法。但这就是现实生活中的情况:通信需要事先商定协议(protocol)。我不知道你老师的意见,但如果你共同定义一个消息标准并将其作为提交作业的一部分写下来,我会给予好评。

您自己发现的“消息之间等待”方法在很大程度上是一种祈祷和希望的解决方案;您希望等待时间超过传输消息所需的时间,如果存在网络打嗝,则该时间可能会相当长。接收方希望 (a) 所有字节立即传送,或者 (b) 如果它轮询数据,则“不再”指示意味着它已读取整个消息。

关于c - 仍然使用 TCP_NODELAY 发送一条消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53795953/

相关文章:

java - 如何向我的服务器添加线程?

c# - 如何检查 byte[] 是否只包含零?

C 基本内存管理实现

c++ - 嵌入式 Linux 中链接 'libstdc++' 库已损坏

objective-c - objective-c 中的 char * 数组

C 中整数的计数排序列表

sockets - 使用 SSL/TLS 比自己处理加密有什么优势

Java程序通过socket接口(interface)与邮件服务器建立TCP连接并发送邮件

c - 发送方缓冲区中未确认数据的 TCP 表示

networking - 防止TCP连接导致UDP丢包