为啥在服务器端和客户端调用 recv 和 send 函数时都使用客户端的文件描述符?

Posted

技术标签:

【中文标题】为啥在服务器端和客户端调用 recv 和 send 函数时都使用客户端的文件描述符?【英文标题】:Why is the client's file descriptor used while calling the recv and send funtions on both server and client sides?为什么在服务器端和客户端调用 recv 和 send 函数时都使用客户端的文件描述符? 【发布时间】:2021-01-30 18:25:06 【问题描述】:

TCP服务器

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/ip.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>

int main()

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1)
    
        printf("socket failed!\n");
        exit(0);
    
    printf("Enter port: ");
    int port;
    scanf("%d",&port);
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = INADDR_ANY;

    int bind_ret = bind(fd, (struct sockaddr*)(&server), sizeof(server));
    if(bind_ret == -1)
    
       printf("bind failed!\n");
       exit(0);
    

    int listen_ret = listen(fd, 10);
    if(listen_ret == -1)
    
           printf("listen failed!\n");
           exit(0);
    

    struct sockaddr_in client;
    int l = sizeof(client);
    int client_fd = accept(fd, (struct sockaddr*)(&client), &l);
    if(client_fd == -1)
    
        printf("accept failed!\n");
        exit(0);
    

    while(1)
    
        char msg_recv[50];
        int recv_ret = recv(client_fd, msg_recv, sizeof(msg_recv),0);
        if(recv_ret == -1)
        
            printf("recv failed!\n");
            exit(0);
        
    
        msg_recv[recv_ret]='\0';
        if(strcmp("bye",msg_recv)==0)
        
            exit(0);
        
    
        printf("Message recieved: %s\n",msg_recv);
    
        char msg_send[50];
        printf("Enter message: ");
        scanf(" %s",msg_send);
        int send_ret = send(client_fd, msg_send, strlen(msg_send),0);
        if(send_ret == 0)
        
            printf("send failed!\n");
        
    
        if(strcmp("bye",msg_send) == 0)
         exit(0);
    

TCP客户端

#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/ip.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>

int main()
 int fd = socket(AF_INET, SOCK_STREAM, 0);
  if(fd == -1)
   
    printf("socket failed!\n");
    exit(0);
  

  int port;
  printf("Enter port number: ");
  scanf("%d",&port);

  struct sockaddr_in client;

  client.sin_family = AF_INET;
  client.sin_port = htons(port);
  client.sin_addr.s_addr = INADDR_ANY;

  int connect_ret = connect(fd, (struct sockaddr*)(&client), sizeof(client));
  if(connect_ret == -1)
  
    printf("connect failed!\n");
    exit(0);
  

  while(1)
  
    printf("Enter message: ");
    char msg_send[50];
    scanf("%s",msg_send);

    int send_ret = send(fd, msg_send, strlen(msg_send), 0);
    if(send_ret == -1)
    
        printf("send failed!\n");
        exit(0);
     

    if(strcmp("bye", msg_send)==0)
    
        exit(0);
    

    char msg_recv[50];
    int recv_ret = recv(fd, msg_recv, sizeof(msg_recv), 0);
    if(recv_ret == -1)
    
        printf("recv failed!\n");
        exit(0);
    
    msg_recv[recv_ret]= '\0';
    if(strcmp("bye", msg_recv) == 0)
     exit(0);
 
    printf("Message recieved: %s \n",msg_recv);
  
 

在上面的Server程序中,recvsend是通过传递client_fd作为参数调用的,而在Client的程序中,recvsend是通过传递fd作为参数调用的论点。我想知道为什么在服务器端我们没有像在客户端那样使用它自己的套接字文件描述符?

【问题讨论】:

答案很简单:尝试将第二个客户端连接到您的服务器! 【参考方案1】:

服务器的fd 描述符是一个listen()'ing 套接字。它不能执行任何 I/O,只能接收传入的客户端连接。 accept()fd 的队列中拉出一个挂起的客户端连接,并返回一个可以与该客户端执行 I/O 的新套接字描述符。

客户端的fd描述符是一个connect()'ing socket。一旦连接被接受,它就可以与服务器执行 I/O。

【讨论】:

以上是关于为啥在服务器端和客户端调用 recv 和 send 函数时都使用客户端的文件描述符?的主要内容,如果未能解决你的问题,请参考以下文章

socket服务端和客户端

网络数据传输,recv && send?没那么简单!

网络数据传输,recv && send?没那么简单!

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

Linux 套接字:如何让 send() 等待 recv()

Recv-Q+Send-Q>写入字节