Omri Ziner
Omri Ziner

Reputation: 83

Send and receive data using select() function

I'm writing client code that is talking with a server, sending and receiving data. I'm using select function to monitor both file descriptors - 0 as the stdin fd and 4(socket_dect) as the socket fd. the main idea is to find whitch of the fd's is active at the moment, if the STDING is active, that ill read it and send the data to the server, if the socket fd is active then ill recive the data and print it. I don't know why but nothing happens when I run this client. this is my code :

// chat client // written by omri

#include <stdio.h>
#include <sys/socket.h> 
#include <sys/select.h>
#include <arpa/inet.h> //inet_addr
#include <netinet/in.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>


#define PORT 9034 // defined port like the server
#define STDIN 0

void main()
{
    struct timeval tv; // time values for select function
    int activity = 0 ;
    int ready; // contains the result of the select function
    char buf[256];
    int len = strlen(buf);
    int byte_sent,i;
    int socket_dect; // creating socket descriptor
    struct sockaddr_in ServerInfo;
    fd_set readfds;
    
    // creating a new socket, its a number represent a file descriptor
    // socket args : 1)ip protocol ipv4,second tcp/udp, third is number of protocol used
    socket_dect = socket(AF_INET,SOCK_STREAM,0);

    if(socket_dect == -1){
        perror("error creating socket");
    }
    // fill the values of the server
    ServerInfo.sin_family = AF_INET; // ipv4
    ServerInfo.sin_port = htons(PORT); // port number
    //ServerInfo.sin_addr = 127.0.0.1; 
    inet_pton(AF_INET, "127.0.0.1", &ServerInfo.sin_addr);//insert the ip to the sin addr
   
    //fill the values of the time for the select function
    tv.tv_sec = 5; // 5 sec
    tv.tv_usec = 0; // 0 mili sec
    FD_ZERO(&readfds); // clear the socket set
    for(i = 0; i<= socket_dect; i++){
        FD_SET(i,&readfds);// set the sockets
    }
    
    // making the connection to the server
    //ServerInfo.sin_addr.s_addr = inet_addr("127.0.0.1"); // another way to put ip addr
    connect(socket_dect,(struct sockaddr *)&ServerInfo,sizeof(ServerInfo)); // connected to the server
    printf("after connect");
    while(1){
        ready = select(socket_dect,&readfds,NULL,NULL,&tv); 
        printf("%d is ready",ready);
        if(ready < 0){
            perror("select error");
            printf("select error");
        }
        // reading from STDIN to buff
        else if(ready == STDIN_FILENO){
            if(fread(buf,256,1,&readfds) < 0){
                printf("read error");
                perror("read error");
            }   
            if(send(socket_dect,buf,len,NULL) < 0){
                perror("send connection");
                printf("send error");
            }//end if send
        }//end elseif STDIN
        else if(ready == socket_dect){
            if(recv(socket_dect,buf,len,0) < 0 ){
                printf("recv error");
            }
            printf("data recived is :%s",buf);   
        }//end elseif
        else{
            printf("none is ready");
        }
    }//end while
}//end main

Upvotes: 3

Views: 837

Answers (1)

alk
alk

Reputation: 70883

For starters two plus more issues.

This

ready = select(socket_dect,&readfds,NULL,NULL,&tv); 

should be

ready = select(socket_dect + 1, &readfds, NULL, NULL, &tv); 

From man select:

nfds is the highest-numbered file descriptor in any of the three sets, plus 1.


Instead of

if(ready == STDIN_FILENO)

use

if (FD_ISET(STDIN_FILENO, &readfds)

select() modifies the parameters passed, so you need to re-initialise them every time before calling select(), that is inside the loop.


Also you must test all system calls for their outcome. This includes connect().


Also^2 you may not assume recv() returns as many bytes as it was told to (len here). It may return having received few. To make sure you got as much as you wanted loop around recv() counting.

Upvotes: 3

Related Questions