Search code examples
socketstcpclientsendrecvtcpserver

Why is the client's file descriptor used while calling the recv and send funtions on both server and client sides?


TCPServer

#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);
    }
}

TCPClient

#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);
  }
 }

In the above program for Server, recv and send were called by passing client_fd as the argument, while in the program for Client, recv and send were called by passing fd as the argument. I wanted to know why on the server side we did not use its own socket file descriptor like we did on the client side?


Solution

  • The server’s fd descriptor is a listen()’ing socket. It can’t perform any I/O, only receive incoming client connections. accept() pulls a pending client connection from fd’s queue and returns a new socket descriptor that can perform I/O with that client.

    The client’s fd descriptor is a connect()‘ing socket. It can perform I/O with the server once its connection has been accepted.