Im trying to make a basic non blocking chat client, but i cant really understand select()
and FD_ISSET()
. im trying to listen to the socket with the code below, but it wont work, it doesn't print anything, why not?
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
int main(int argc, char const* argv[])
{
fd_set readfs;
char sendline[100];
char str[100];
char *some_addr;
int listen_fd, comm_fd;
struct sockaddr_in servaddr;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
//Socket error
if (listen_fd == -1) {
printf("Error on getting socket, Exiting!\n");
return 1;
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port=htons(22000);
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listen_fd, 10);
comm_fd = accept(listen_fd, (struct sockaddr *) NULL, NULL);
FD_ZERO(&readfs);
FD_SET(comm_fd, &readfs);
while (1)
{
select(listen_fd,&readfs, NULL, NULL, NULL);
if(FD_ISSET(listen_fd,&readfs))
{
bzero(str,100);
read(listen_fd,str,100);
printf("%s", str);
/* write(listen_fd, "read!", strlen(str)+1); */
}
}
return 0;
}
EDIT: My code trying to Connect to the server:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include<string.h>
int main(int argc,char **argv)
{
int sockfd,n;
char sendline[100];
char recvline[100];
struct sockaddr_in servaddr;
sockfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof servaddr);
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(22000);
inet_pton(AF_INET,"127.0.0.1",&(servaddr.sin_addr));
connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
while(1)
{
bzero( sendline, 100);
bzero( recvline, 100);
fgets(sendline,100,stdin); /*stdin = 0 , for standard input */
write(sockfd,sendline,strlen(sendline)+1);
read(sockfd,recvline,100);
printf("%s\n",recvline);
}
return 0;
}
Four major problems, here:
Your select()
call and the read/write loop should be using comm_fd
, not listen_fd
. If you call select()
on listen_fd
it'll return when there is an accept()
able connection available, but you want to wait on the connected socket you already have for input, so use comm_fd
.
The first argument to select()
should be the highest file descriptor in the sets plus one. Since you only have one file descriptor, here, it should be comm_fd + 1
.
You should move your FD_ZERO
and FD_SET
macros inside the while
loop, and execute them prior to every select()
call, because select()
is going to modify those fd sets you pass to it.
You don't check the return from your system calls for errors. You should.
Other points:
bzero()
has been removed from POSIX for quite some time, now, you should be using the standard memset()
instead.
You shouldn't pass INADDR_ANY
though htons()
, just use it as it is.
It's only a comment in your program, but while STDIN_FILENO
may be 0
, stdin
is a FILE
pointer, and is not 0
.