Reputation: 83
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
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