通过 send() recv() 发送多条消息,Socket 编程,C

Posted

技术标签:

【中文标题】通过 send() recv() 发送多条消息,Socket 编程,C【英文标题】:Sending multiple messages via send() recv(), Socket programming, C 【发布时间】:2011-05-09 12:32:32 【问题描述】:

我正在尝试制作一个程序(客户端),它可以根据用户的请求向服务器发送消息。精简代码如下:

客户:

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 也可能在这里返回错误,并且检查绑定和侦听返回值也是一个好习惯。) 在客户端调用 connect() 时出现错误,并出现错误消息“文件描述符错误” 请记住 TCP 是一个流。它没有消息。您正在接收 160 字节,这可能是客户端发送的多个应用程序消息。 即使消息以 '\0' 终止,它也会发送 160 个字节,并且我在 send() 中使用 strlen(message) 作为 3dr 参数? 我应该顺便发送 strlen(message)+1 作为第三个参数。否则它不会发送 '\0' 终止符。 【参考方案1】:

你的客户端程序也犯了同样的错误,第一次打开套接字但第一次连接完成后你关闭了套接字,所以下一次循环中套接字描述符无效,你需要重新打开套接字但丢失了,请从顶部删除套接字调用并在 while 循环的开头添加以下行

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

【讨论】:

【参考方案2】:

问题是您正在关闭侦听套接字sock,而不是客户端套接字clisock

【讨论】:

感谢您的回复。我纠正了错误。但是,它仍然不起作用。它不再在无限循环中运行,但它似乎仍然无法连接。我已经检查了 socket、bind、listen 等的所有返回值。我在客户端调用 connect() 时似乎收到了一个错误,以及一条错误消息“Bad file descriptor”。【参考方案3】:
servaddr.sin_addr.s_addr = inet_addr(<ip_address_of_server>);

在您的客户端代码中使用以下代码而不是上面的行

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

还要对以下函数执行错误检查。

【讨论】:

以上是关于通过 send() recv() 发送多条消息,Socket 编程,C的主要内容,如果未能解决你的问题,请参考以下文章

Socket send函数和recv函数详解

ZMQ:socket_send/recv 阻塞

Python网络编程之socket之send和recv原理剖析

为啥我不能激发 TCP 将 send() 拆分为多个 recv()

Linux C语言 C/S程序,客户端发送的数据和服务器端接收到的数据不一样,求解

Socket send函数和recv函数详解