使用select()系统调用监听标准输入和服务器 [英] Using select() system call for listening on stdin and the server
问题描述
我想用select系统调用复STDIN和的sockfd(连接到服务器),使得我必须听这两种标准输入和的sockfd并依据其中的数据可用于读取I必须进一步进行。
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.
请注意:#定义STDIN 0
Note: #define STDIN 0
这是当我做下面会发生什么。
This is what happens when I do the following.
- 我连接到服务器通常的方式[插座()然后连接()]
- 我想补充STDIN和连接插座描述符的sockfd到FD_SET(命名为读集),意味着读数。
- 然后调用选择()。
- 使用FD_ISSET来确定哪些fd是准备读。
这个问题设置是FD_ISSET始终是真实的同时为FD。一旦我得到连接到服务器我看到FD_ISSET(的sockfd,&安培;读集)始终是真实的,所以是FD_ISSET(STDIN,&安培;读集)是否服务器发送数据与否,或者如果我从键盘或不输入数据。
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;
}
推荐答案
什么是STDIN?有它在声明的stdin &所述; stdio.h中&GT;
,是FILE *,而不是一个文件描述符所以不能在fdset和STDIN_FILENO,这是用于在&LT; unistd.h中方式&gt;
,是一个文件描述符,因此可以用fdsets使用
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.
顺便说一句,在&LT; stdio.h中&GT;
还有一个功能的fileno()
返回文件一个FILE *的描述符(取决于你的编译标志,你可能需要一些定义宏功能来获得声明)。
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).
这篇关于使用select()系统调用监听标准输入和服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!