Search code examples
csocketstcpnetwork-programmingposix-select

C socket: recv and send simultaneously


I am trying to make a client server chat application with a single server and multiple client scenario. My server is working but I cant get the client working. I am using select() function to select whether I should recv() or send(). Here is my code for client implementation.

main()
{
int sockfd;
struct sockaddr_in serv_addr;

int i, sent;
char buf[100];
char buff[100];

/*
Opening a socket 
Check whether opening is successful or not
*/
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    printf("Unable to create socket\n");
}
printf("Socket created\n");


serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(6000);

/*
Establish a connection with the server process
*/
if((connect(sockfd, (struct socketaddr *)&serv_addr, sizeof(serv_addr)))<0){
    printf("Unable to connect to server\n");
    exit(0);
}

printf("Client connected\n");

while(1){

    for(i=0; i<100; i++){
        buf[i] = '\0';
        buff[i] = '\0';
    }

    fd_set rfd, wfd;
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO( &rfd);
    FD_ZERO( &wfd);

    FD_SET( sockfd, &rfd);
    //FD_SET( sockfd, &wfd);
    FD_SET( 0, &wfd);

    if( (select( sockfd + 1, &rfd, &wfd, NULL, &tv) < 0)) {
        printf(" Select error \n");
        exit(0);
    }

    if( FD_ISSET( sockfd, &rfd)) { // we got data ... need to read it
        recv(sockfd, buff, 100, 0);
        printf("Received result from server = %s\n",buff);
    }

    if( FD_ISSET( 0, &wfd)) {
        fflush(stdin);
        printf(">");
        gets(buf);
        sent = send(sockfd, buf, strlen(buf) + 1, 0);
        printf("-------------Sent %d bytes to server--------------\n", sent);
    }
}
printf("----------------Closing client------------------ \n");
close(sockfd);
}

Each client should get the message sent by one client to the server just like a chat application.


Solution

  • The problem is that you check if you can write to the standard input file descriptor. That makes no sense, you should check if you can read from it.

    That is, you should add STDIN_FILENO to the read set too, and not have a write set at all.