通过send() recv()发送多个消息,套接字编程,C

6
我是一个有用的助手,可以为您翻译文本。

我正在尝试制作一个程序(客户端),该程序可以在用户请求时向服务器发送消息。以下是简化代码:

客户端:

int main(int argc, char **argv) {

  struct sockaddr_in servaddr;
  int sock = socket(AF_INET, SOCK_STREAM, 0);

  memset(&servaddr, 0, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(6789);
  servaddr.sin_addr.s_addr = inet_addr(<ip_address_of_server>);

  while(1) {

    char message[161];
    fgets(message, 161, stdin);

    /* Replacing '\n' with '\0' */
    char *tmp = strchr(message, '\n');
    if (tmp) *tmp = '\0';

    connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr));
    send(sock, message, strlen(message), 0);
    close(sock);
  }
}

服务器:

int main(int argc, char **argv) {

  struct sockaddr_in servaddr;  
  int sock = socket(AF_INET, SOCK_STREAM, 0);

  memset(&servaddr, 0, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(6789);

  bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr));  
  listen(sock, 5);

  while(1) {
    int clisock = accept(sock, (struct sockaddr *) NULL, NULL);

    if (clisock >= 0) {
      int messageLength = 160;
      char message[messageLength+1];
      int in, index = 0, limit = messageLength;

      while ((in = recv(clisock, &message[index], messageLength, 0)) > 0) {
        index += in;
        limit -= in;
      }

      printf("%s\n", message);
    }

    close(clisock);
  }
}

现在,这对我发送的第一条消息有效。但是随后它无法建立另一个连接(当尝试在客户端程序中连接时,我收到错误消息“坏文件描述符”)。有人能看出我误解了什么吗?谢谢:)


无论是 accept 调用还是 recv 调用都可能返回错误。检查它并且原因会变得更加清晰。perror() 对此非常有帮助。(注意:如果 accept 返回错误,close 在这里也可能返回错误,而且检查 bind 和 listen 的返回值也是一个好习惯。) - Flexo
我在客户端调用connect()时收到一个错误,并且出现一个错误消息“坏的文件描述符”。 - ragnaroh
1
请记住,TCP 是一个流。它没有消息的概念。你正在接收 160 字节,这可能是客户端发送的多个应用程序消息。 - nos
即使消息以'\0'结尾,它仍然发送160个字节,并且我在send()中使用strlen(message)作为第三个参数,这是什么原因? - ragnaroh
我应该发送strlen(message)+1作为第三个参数。否则它不会发送'\0'终止符。 - ragnaroh
它不是发送160个字节,而是发送strlen(message)个字节。 - nos
3个回答

4

你的客户端程序也犯了同样的错误,第一次打开套接字后,完成第一个连接后关闭套接字,所以在循环中下一次使用套接字描述符时它是无效的,你需要重新打开套接字,但这个步骤缺失了,请将套接字调用从顶部移除,并在while循环开始处添加以下行:

int sock = socket(AF_INET, SOCK_STREAM, 0);

2
servaddr.sin_addr.s_addr = inet_addr(<ip_address_of_server>);

在您的客户端代码中,使用以下代码替换上述代码

inet_pton(AF_INET,"<ipofserver>",&servaddr.sin_addr);

请对以下函数进行错误检查。


2
问题在于您关闭了监听套接字sock,而不是客户端套接字clisock

感谢您的回复。我已经纠正了错误。然而,它仍然无法工作。它不再运行在一个无限循环中,但似乎仍然无法连接。我已经检查了socket、bind、listen等所有返回值。当我在客户端调用connect()时,似乎出现了一个错误消息“坏文件描述符”。 - ragnaroh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接