学习Linux C-网络调用:select

3 篇文章 0 订阅
1 篇文章 0 订阅

学习Linux c,首先需要写的是一个基于tcp的网络调用server,下面逐个注释分析代码逻辑。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#define SERV_PORT 6677
#define LENGTH_OF_LISTEN_QUEUE  20
#define MAXLINE 100

int main(int argc, char **argv)
{
    int i,maxi,maxfd,listenfd,connfd,sockfd;
    int nready,client[FD_SETSIZE];

    /* 
    /usr/include/sys/types.h 
    */
    ssize_t n; 

    /*
    /usr/include/sys/select.h
    可以理解为一个集合,这个集合中存放的是文件描述符(filedescriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符
    */
    fd_set rset, allset;
    char buf[MAXLINE];

    /*
    /usr/include/netinet/in.h
    */
    socklen_t clilen;
    struct sockaddr_in cliaddr, servaddr;

    /*
    /usr/include/sys/socket.h
    */
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if( listenfd < 0 )
    {
        printf("create socket failed!\n");
        exit(1);
    }

    /*
    /usr/include/strings.h
    */
    bzero(&servaddr, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))
    {
        printf("server bind port %d failed!\n", SERV_PORT);
        exit(1);
    }

    if(listen(listenfd, LENGTH_OF_LISTEN_QUEUE))
    {
        printf("Server Listen Failed!\n");
                exit(1);
    }

    maxfd = listenfd;
    maxi = -1;

    for(i = 0; i < FD_SETSIZE; i++)
        client[i] = -1;

    FD_ZERO(&allset);
    FD_SET(listenfd, &allset);

    for(;;)
    {
        rset = allset;
        /*
        负值:select错误 正值:某些文件可读写或出错 0:等待超时,没有可读写或错误的文件
        */
        nready = select(maxfd+1, &rset , NULL , NULL, NULL);
        //printf("nready:%d\n", nready);
        printf("maxfd:%d\n", maxfd);

        if(FD_ISSET(listenfd, &rset))
        {
            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);

            for(i = 0; i< FD_SETSIZE; i++)
            {
                if(client[i] < 0){
                    client[i] = connfd;
                    break;
                }
            }

            if (i == FD_SETSIZE)
            {
                printf("too many clients\n");
                exit(1);
            }
            FD_SET(connfd, &allset);

            if(connfd > maxfd)
                /* int maxfd是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1 */
                maxfd=connfd;

            if(i > maxi)
                maxi = i;

            if(--nready <= 0)
                continue;

        }

        for (i = 0; i<=maxi; i++)
        {
            if((sockfd = client[i]) < 0)
                continue;

            if(FD_ISSET(sockfd, &rset))
            {
                /*从socket读取内容*/
                if((n = read(sockfd, buf, MAXLINE)) == 0)
                {
                    close(sockfd);
                    FD_CLR(sockfd, &allset);
                    client[i] = -1;
                }else
                {
                    /*把内容写入socket*/
                    write(sockfd, buf, n);
                }

                if( --nready <= 0 )
                    break;
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值