Linux 网络编程(多路复用)

  • 服务器端代码
#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<sys/socket.h>  
#include<sys/types.h>  
#include<unistd.h>  
#include<netinet/in.h>
#include <errno.h>
#include <sys/fcntl.h>


typedef struct _CLIENT{
    int fd;                                  
    struct sockaddr_in addr;      
    char recvbuf[1024];     
}CLIENT_S;

int main(int argc, char** argv){

    int socketfd,new_fd;
    CLIENT_S sock_list[10];
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    struct timeval tv;
    char recvbuf[1024];
    int res;
    int max;
    int len,nbytes;
    int port = 8001;
    int i;

    for(i = 0; i < 10; i ++){
        sock_list[i].fd = -1;
    }

    if((socketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == 0){
        fprintf(stderr, "socket Error:%s
a", strerror(errno));   
        exit(1);
    }

    //设置为非阻塞
    if (fcntl(socketfd, F_SETFL, O_NONBLOCK) == -1) {  
        fprintf(stderr, "fcntl Error:%s
a", strerror(errno));   
        exit(1);  
    }

    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr =  htonl(INADDR_ANY);

    if((bind(socketfd, &server_addr, sizeof(server_addr))) == -1){
        fprintf(stderr, "bind Error:%s
a", strerror(errno));   
        exit(1);
    }

    if(listen(socketfd, 10) == -1){
        fprintf(stderr, "listen Error:%s
a", strerror(errno));   
        exit(1);
    }


    sock_list[0].fd = socketfd;
    max = socketfd;
    fd_set watchset;//select所需要的文件描述符  
    FD_ZERO(&watchset); 
    //将监听socket放入扫描集合 
    FD_SET(socketfd, &watchset);

    while(1){
            FD_ZERO(&watchset); 

            FD_SET(socketfd, &watchset);
            for(i = 0; i < 10; i ++){
                if (sock_list[i].fd != -1) {  
                    FD_SET(sock_list[i].fd, &watchset);  
                }
            }

            res = select(max + 1, &watchset, NULL, NULL, NULL);

            if(-1 == res){
                fprintf(stderr, "select Error:%s
a", strerror(errno));   
                exit(1);
            }else if(0 == res){
                printf("Select() break and the return num is");
                continue;
            }else{
                if(FD_ISSET(socketfd, &watchset)){
                    len = sizeof(struct sockaddr_in);
                    if ((new_fd = accept(socketfd, 
                        (struct sockaddr *)&client_addr, 
                        &len)) == -1) {   
                        fprintf(stderr, "Accept error:%s
a", strerror(errno));   
                        exit(1);   
                    }

                    for(i = 1; i < 10; i ++){
                        if (sock_list[i].fd == -1) {  
                            sock_list[i].fd = new_fd;
                            sock_list[i].addr = client_addr;  
                            break;
                         }
                    }

                    fprintf(stderr, "new connect: %d
", sock_list[i].fd);  

                    //将其放入socket的监听集合
                    FD_SET(new_fd, &watchset);  
                    if (max < new_fd) {  
                        max = new_fd;  
                    }  
  
                    continue; 
                }else{
                    for (i  = 1; i < 10; i++) { //data  
                        if (sock_list[i].fd == -1)  
                            continue;  
                        if (!FD_ISSET(sock_list[i].fd, &watchset)) {  
                            continue;  
                        }

                        nbytes = recv(sock_list[i].fd, sock_list[i].recvbuf, sizeof(sock_list[i].recvbuf), 0);
                        recvbuf[nbytes] = '';

                        printf("recv data is:%s
",sock_list[i].recvbuf); 

                        break;
                    }
                }
            }
    }//while(1)

    exit(0);
}
原文地址:https://www.cnblogs.com/Fredric-2013/p/4549317.html