C unix网络编程选择函数始终返回1(已解决)

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&

学习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 <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