簡體   English   中英

Unix網絡編程選擇功能總是返回1(已保存)

[英]unix network programming select function always return 1( resoved)

使用gdb tcpserv學習c語言中的套接字編程,select函數始終返回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);

文件:sockheader.c內容:

#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; 
}

文件:tcpcli05.c內容:

#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;
}

文件:tcpserv05.c內容:

#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;
}

然后

gcc -o tcpserv05 -g sockheader.c tcpserv05.c
gcc -o tcpcli05 -g sockheader.c tcpcli05.c

./tcpserv05

./tcpcli05 127.0.0.1

在cli中,我輸入了諸如“ hi,test”之類的內容。 serv不返回任何東西。 我gdb tcpserv05然后發現nready總是1。 所以--nready <= 0為true,繼續。 程序沒有轉到下面。

我需要一些幫助,首先謝謝。

我找到問題了。

我寫錯了代碼:

讀取(stdin,buf,MAXLINE)

stdin是FILE *,fread,fwrite,fclose將使用stdin。

ssize_t read(int fd,void * buf,size_t count);

所以我改用fileno(stdin),程序正常工作。

select返回1,因為這是具有事件的文件描述符的數量。 如果有超時,它將返回0,如果更多文件描述符具有事件,則將返回更大的數字。

您可能要使用poll(2)而不是較早的select(2) 閱讀有關C10K問題的信息

由於select可能會修改其fd_set掩碼,因此應在循環設置它們(通常, fd_set只是一個數組,因此分配rset = allset;不要執行您想要的操作)。

不要忘記在適當的位置調用fflush(3) (例如,在執行selectpoll之前先執行fflush(NULL)

還考慮使用strace(1)進行調試。

始終測試每個 syscalls(2)是否失敗(使用perror

有關此相關問題,請參閱評論。

始終使用gcc -Wall -Wextra -g編譯,並改進源代碼,直到完全沒有任何警告為止。 順便說一句, bzero(3)已被明確棄用(即已過時),您不應使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM