C unix网络编程选择函数始终返回1(已解决)
学习c语言中的socket编程 使用gdb tcpserv,选择函数总是返回1,我不知道为什么。 英语不好,所以我把代码贴在这里。有人帮忙吗 文件:sockheader.h 内容:C unix网络编程选择函数始终返回1(已解决),c,linux,sockets,select,C,Linux,Sockets,Select,学习c语言中的socket编程 使用gdb tcpserv,选择函数总是返回1,我不知道为什么。 英语不好,所以我把代码贴在这里。有人帮忙吗 文件:sockheader.h 内容: #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <sys/socket.h> #include <string.h> #include <signal.h&
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <signal.h>
#include <sys/select.h>
#define SERV_PORT 11211
#define SA struct sockaddr
#define LISTENQ 5
#define MAXLINE 1024
typedef void Sigfun(int);
int Socket(int family, int type, int protocol);
int Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
int Listen(int sockfd, int backlog);
int Accept(int sockfd, struct sockaddr *chiaddr, socklen_t *addrlen);
int Close(int sockfd);
int Connect(int sockfd, const struct sockaddr *sa, socklen_t salen);
void Writen(int sockfd, char *writeline, int len);
int str_echo(int sockfd);
int str_echo2sum(int sockfd);
int str_cli(int sockfd);
void sig_chld(int signo);
#include "sockheader.h"
int Socket(int family, int type, int protocol)
{
int fd;
if( (fd = socket(family, type, protocol)) < 0 )
{
perror("socket error!\n");
exit(-1);
}
return fd;
}
int Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen)
{
int bindfd;
if( (bindfd = bind(sockfd, myaddr, addrlen)) < 0 )
{
perror("bind error");
exit(-1);
}
return bindfd;
}
int Listen(int sockfd, int backlog)
{
int res ;
if( (res = listen(sockfd, backlog) ) < 0 )
{
perror("Listen error");
exit(-1);
}
return res;
}
int Accept(int sockfd, struct sockaddr *chiaddr, socklen_t *addrlen)
{
int res ;
if( (res = accept(sockfd, chiaddr, addrlen)) < 0 )
{
perror("accept error");
exit(-1);
}
return res;
}
int Close(int sockfd)
{
close(sockfd);
}
int Connect(int sockfd, const struct sockaddr *sa, socklen_t salen)
{
int res ;
if ( (res = connect(sockfd, sa, salen)) < 0)
perror("connect error");
return res;
}
void Writen(int sockfd, char *writeline, int len)
{
write(sockfd, writeline, len);
}
int str_echo(int sockfd)
{
char readline[MAXLINE];
char sendline[MAXLINE];
int n;
again:
while( (n = read(sockfd, readline, MAXLINE)) > 0 )
{
fputs("read str:\n", stdout);
readline[n] = '\0';
strcpy(sendline, "recive str:");
strcat(sendline, readline);
Writen(sockfd, sendline, strlen(sendline) + 1);
if(fputs(readline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("out while\n", stdout);
if (n < 0 )
goto again;
}
int str_echo2sum(int sockfd)
{
long arg1, arg2;
char readline[MAXLINE];
int n;
again:
while( (n = read(sockfd, readline, MAXLINE)) > 0 )
{
if( sscanf(readline, "%ld%ld", &arg1, &arg2) == 2 )
{
snprintf(readline, sizeof(readline), "%ld\n", arg1 + arg2);
}
else
{
snprintf(readline, sizeof(readline), "input error\n");
}
n = strlen(readline);
Writen(sockfd, readline, strlen(readline) + 1);
if(fputs(readline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("out while\n", stdout);
if (n < 0 )
goto again;
}
int str_cli(int sockfd)
{
char charline[MAXLINE], recvline[MAXLINE];
while(fgets(charline, MAXLINE, stdin) != NULL)
{
fputs("write string\n", stdout);
Writen(sockfd, charline, strlen(charline) + 1);
if(read(sockfd, recvline, MAXLINE) == 0)
{
perror("str_cli:server terminated prematurely");
}
if(fputs(recvline, stdout) == EOF)
{
perror("fputs error");
}
}
fputs("cli:out while\n", stdout);
}
int str_cli2(int sockfd)
{
int maxfd1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n;
stdineof = 0;
FD_ZERO(&rset);
for(;;)
{
if(stdineof == 0)
{
FD_SET(fileno(stdin), &rset);
}
FD_SET(sockfd, &rset);
maxfd1 = fileno(stdin) > sockfd ? fileno(stdin) + 1 : sockfd + 1 ;
select(maxfd1, &rset, NULL, NULL, NULL);
if(FD_ISSET(sockfd, &rset))
{
if( ( n = read(sockfd, buf, MAXLINE) ) == 0)
{
if(stdineof == 1)
{
return ;
}
else
{
perror("str_cli2:server terminated ");
exit(-1);
}
}
Writen(fileno(stdout), buf, n );
}
if( FD_ISSET(fileno(stdin), &rset) )
{
if( ( n = read(stdin, buf, MAXLINE) ) == 0)
{
stdineof = 1;
shutdown(sockfd, SHUT_WR);
FD_CLR(fileno(stdin), &rset);
continue;
}
Writen(sockfd, buf, n);
}
}
}
void sig_chld(int signo)
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
printf("child %d terminated\n", pid);
}
return;
}
#include "sockheader.h"
int main(int argc, char const *argv[])
{
int sockfd, i;
struct sockaddr_in cliaddr;
for(i = 0; i < 5; i++)
{
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&cliaddr, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &cliaddr.sin_addr.s_addr);
Connect(sockfd, (SA *)&cliaddr, sizeof(cliaddr));
}
str_cli2(sockfd);
return 0;
}
#include "sockheader.h"
int main(int argc, char const *argv[])
{
int i, maxi, maxfd, listenfd, sockfd, connfd;
int nready, client[FD_SETSIZE];
ssize_t n ;
fd_set rset, allset;
char buf[MAXLINE];
struct sockaddr_in servaddr, chiladdr;
socklen_t chlien;
pid_t pid;
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
// inet_pton(AF_INET, INADDR_ANY, &servaddr.sin_addr);
Bind(sockfd, (SA *)&servaddr, sizeof(servaddr));
Listen(sockfd, LISTENQ);
// signal(SIGCHLD, sig_chld);
maxfd = sockfd;
maxi = -1;
for(i = 0; i < FD_SETSIZE; i++)
{
client[i] = -1;
}
FD_ZERO(&allset);
FD_SET(sockfd, &allset);
for(;;)
{
rset = allset;
printf("i walk here \n");
nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
printf("nready:%d\n", nready);
if(FD_ISSET(sockfd, &rset))
{
chlien = sizeof(chiladdr);
if(( connfd = Accept(sockfd, (SA *)&chiladdr, &chlien )) < 0)
{
perror("accept error");
}
printf("new client: %d\n", inet_ntoa(chiladdr.sin_addr));
printf("new client port: %d\n", ntohs(chiladdr.sin_port));
for(i = 0; i < FD_SETSIZE; i++)
{
if(client[i] < 0)
{
client[i] = connfd;
break;
}
}
if(i == FD_SETSIZE)
{
perror("too many clients");
}
printf("connfd: %d\n", connfd);
FD_SET(connfd, &allset);
if(connfd > maxfd)
{
maxfd = connfd;
}
if(i > maxi)
{
maxi = i;
}
if(--nready <= 0 )
{
continue;
}
}
printf("i walk down here \n");
for( i = 0 ; i <= maxi; i++)
{
if( (listenfd = client[i]) < 0)
{
continue;
}
if(FD_ISSET(listenfd, &rset))
{
if( (n = read(listenfd, buf, MAXLINE)) == 0 )
{
Close(listenfd);
FD_CLR(listenfd, &allset);
client[i] = -1;
}
else
{
Writen(listenfd, buf, n);
}
if( --nready < 0 )
{
continue;
}
}
}
}
return 0;
}
在cli中,我输入了一些类似“hi,test”的内容。服务不返回任何内容。
我gdb tcpserv05然后发现nready
始终为1。因此,--nready您可能希望使用,而不是旧的。阅读关于这个问题的文章
由于select
可能会修改其fd\u集
位掩码,因此您应该在循环中设置它们(通常,fd\u集
只是一个数组,因此分配rset=allset;
不做您想做的事情)
不要忘记在适当的位置调用(例如,在任何选择或轮询之前调用fflush(NULL)
)
还可以考虑将其用于调试
始终测试每个故障(使用peror
)
有关详细信息,请参阅评论
始终使用gcc-Wall-Wextra-g
编译并改进您的源代码,直到您没有收到任何警告为止。顺便说一句,已明确弃用(即过时),您不应该使用它。select
返回1,因为这是具有事件的文件描述符的数量。如果您有一个超时,它将返回0,如果更多的文件描述符有事件,它将返回一个更高的数字。我的提示:更好地阅读和构造代码,阅读和遵循是一件痛苦的事情,也容易出错。@weizhao,而不是执行rset=allset编码>然后在select()
中使用rset
,尝试直接在select()
中使用allset
,看看是否有效?我只需编写与书本相同的代码。在书中,他们给出了tcpservselect01.c和strcliselect02.c的演示<代码>选择
返回准备就绪的描述符数量。如果只有一个客户端,则只能返回1
。为什么期望另一个返回值呢?tcpcli05.c对于(i=0;i<5;i++){Connect(sockfd,(SA*)&cliaddr,sizeof(cliaddr));},我认为它将返回5。我认为是错的?rset=allset;这里是代码的来源。tcpcli05.c对于(i=0;i<5;i++){Connect(sockfd,(SA*)&cliaddr,sizeof(cliaddr));},我认为它将返回5。我认为是错的?你有一个监听插座发生了一个事件。
gcc -o tcpserv05 -g sockheader.c tcpserv05.c
gcc -o tcpcli05 -g sockheader.c tcpcli05.c
./tcpserv05
./tcpcli05 127.0.0.1