我想使用select系统调用来复用STDIN和SOCKFD(连接到服务器),这样我必须同时监听STDIN和SOCKFD,并且根据数据的可读位置,我必须继续进行。
注意:#define STDIN 0
当我执行以下操作时会发生这种情况。
这个设置的问题是FD_ISSET对于fd都是正确的。一旦我连接到服务器,我看到FD_ISSET(sockfd,& readset)始终为true,因此FD_ISSET(STDIN,& readset)是否,服务器是否正在发送数据,或者我是否从键盘输入数据。
我可能做错了什么?
/ *连接成功* /
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;
}
答案 0 :(得分:4)
什么是STDIN?在<stdio.h>
中声明了stdin,它是一个FILE *而不是文件描述符,因此不能在fdset和STDIN_FILENO中使用,它在<unistd.h>
中定义并且是文件描述符,因此可以与fdsets一起使用。
BTW,在<stdio.h>
中还有一个函数fileno()
,它返回FILE *的文件描述符(根据你的编译标志,你可能需要定义一些特征宏来获取声明)