仍使用TCP_NODELAY发送一条消息

时间:2018-12-15 18:15:27

标签: c sockets tcp

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

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

在服务器端,我必须将其处理为字符串:name / year / month / day / filename

明确指出,我的客户/服务器应该与其他学生的客户/服务器一起工作。因此,不允许我在每条消息的末尾都设置\ 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),这显然不是最佳选择)。 / p>

预先感谢您的回复

1 个答案:

答案 0 :(得分:1)

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

所有这些都需要建立一种标准方法,供所有学生使用。但这就是现实生活中的情况:通讯需要协议事先达成协议。我不知道您老师的意见,但是如果您集体定义了消息标准并在提交作业时将其写下来,我会给予良好的评价。

您自己发现的“在消息之间等待”方法在很大程度上是您的交叉手指和希望的解决方案;您希望您的等待时间超过传输消息所花费的时间,如果有网络打p,这可能会很大。接收者希望要么(a)一次发送所有字节,要么(b)如果它轮询数据,则“不再”指示意味着它已经读取了整个消息。