I want to use select system call to multiplex STDIN and SOCKFD (connected to a server) such that I must be listening to both STDIN and SOCKFD and depending upon where the data is available for read I must proceed further.
Note: #define STDIN 0
This is what happens when I do the following.
The problem with this set up is that FD_ISSET is always true for both the fd. Once I get connected to the server I see FD_ISSET(sockfd, &readset) is always true and so is FD_ISSET(STDIN, &readset) whether, the server is sending data or not or if I am entering data from keyboard or not.
What could I be doing wrong?
/* connection successful */
FD_ZERO(&connset);
while(1) {
FD_SET(sockfd,&connset); /* add sockfd to connset */
FD_SET(STDIN,&connset); /* add STDIN to connset */
fdmax=sockfd;
if(select(fdmax+1,&readset,NULL,NULL,NULL)<0){
fprintf(stdout, "select() error\n");
exit(0);
}
/* select returned
* check which socket is set
*/
if(FD_ISSET(sockfd,&connset)) {
/*
* Server sends msglen
* client reads msg of length msglen
* client prints it to stdout
* client waits for next activity of its listen sockets
*/
size=4;
ptr=(char *)&msglen;
while(1) {
if((nread=recv(sockfd,ptr,size,0)),MSG_DONTWAIT) {
close(sockfd);
exit(0);
}
size-=nread;
ptr+=nread;
}
bytesToRead = ntohl(msglen);
readbuf = (char *)malloc(sizeof(char)*(bytesToRead+1));
ptr=readbuf;
while(1) {
nread=recv(sockfd,ptr,bytesToRead,MSG_DONTWAIT);
if(nread<=0) {
close(sockfd);
exit(0);
}
bytesToRead-=nread;
ptr+=nread;
}
/* msg read successfully */
*ptr='\0';
fprintf(stdout, "in: %s\n",readbuf);
free(readbuf);
}
if(FD_ISSET(STDIN,&connset)) {
/* data at STDIN */
fgets(buf,2,stdin); /* read the first newline char (< enter >) */
fprintf(stdout,"Enter msg: ");
fgets(buf,MAXLEN,stdin); /* read the msg */
buf[strlen(buf)-1]='\0';
msglen = htonl((uint32_t)(strlen(buf)-1));
ptr = (char *)&msglen;
bytesToSend = sizeof(uint32_t);
cnt = bytesToSend;
while(cnt>0) {
if((nsent=send(sockfd,ptr,cnt,0))>0) {
cnt-=nsent;
ptr+=nsent;
}
else {
fprintf(stdout,"send error\n");
exit(0);
}
}
ptr=buf;
bytesToSend=(uint32_t)(strlen(buf)-1);
cnt=bytesToSend;
while(cnt>0) {
if((nsent=send(sockfd,ptr,cnt,0))>0) {
cnt-=nsent;
ptr+=nsent;
}
else {
fprintf(stdout,"send error\n");
exit(0);
}
}
}
}
return 0;
}
What is STDIN? There is stdin which is declared in <stdio.h>, is a FILE* and not a file descriptor so can't be used in an fdset and STDIN_FILENO, which is defined in <unistd.h> and is a file descriptor and thus can be used with fdsets.
BTW, in <stdio.h> there is also a function fileno() which returns the file descriptor of a FILE* (depending on your compilation flags, you may need to define some feature macros to get the declaration).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With