Linux 网络编程九(select应用--大并发处理)

//网络编程服务端
/*
 * 备注:因为客户端代码、辅助方法代码和epoll相同,所以select只展示服务器端代码
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>//htons()函数头文件
#include <netinet/in.h>//inet_addr()头文件
#include <fcntl.h>
#include <sys/select.h>
#include <time.h>
#include "pub.h"

#define MAXSOCKET 1024

int main(int arg, char *args[])
{
    if (arg < 2)
    {
        printf("please print one param!\n");
        return -1;
    }
    //create server socket
    int listen_st = server_socket(atoi(args[1]));
    if (listen_st < 0)
    {
        return -1;
    }
    //设置非阻塞文件描述符
    setnonblock(listen_st);
    int i = 0;
    int maxfd = 0; //最大的socket,select函数第一个参数使用
    /*
     *建立客户端连接池
     */
    int client[MAXSOCKET]; //select最大支持1024个socket连接
    //将所有的客户端连接池初始化,将每个成员都设置为-1,表示无效
    for (; i < MAXSOCKET; i++)
    {
        client[i] = -1;
    }
    maxfd = listen_st;    //程序刚开始执行时,只有服务端socket,所以服务端socket最大
    //定义一个事件数组结构
    fd_set allset;
    while (1)
    {
        //初始化一个fd_set对象
        FD_ZERO(&allset);
        //将服务器端socket放入事件数组allset中(服务端socket需要特殊处理,所以没有放入socket池中)
        FD_SET(listen_st, &allset);
        //先假设最大的socket就是服务器端socket
        maxfd = listen_st;
        //遍历socket池 找出值最大的socket
        for (i = 0; i < MAXSOCKET; i++)
        {
            if (client[i] != -1)
            {
                //将socket池中的所有socket都添加到事件数组allset中
                FD_SET(client[i], &allset);
                if (client[i] > maxfd)
                {
                    maxfd = client[i];    //maxfd永远是值最大的socket
                }
            }
        }
        //开始等待socket发生读事件
        int rc = select(maxfd + 1, &allset, NULL, NULL, NULL);
        /*
         * select函数返回之后,allset数组的数据产生变化,现在allset数组里的数据是发生事件的socket
         * select和epoll不同,select每次返回后,
         * 会清空select池中的所有socket,所有的socket等select返回后就被清除了
         * 所以必须由程序建立一个socket池,每次都将socket池中的socket加入到select池中
         * select不会为程序保存socket信息,这与epoll最大的不同,
         * epoll添加到events中的socket,如果不是程序员清除,epoll永远保留这些socket
         */
        if (rc < 0)
        {
            //select函数出错,跳出循环
            printf("select failed ! error message:%s\n", strerror(errno));
            break;
        }
        //判断是否是服务器socket接收到数据,有客户端连接
        if (FD_ISSET(listen_st, &allset))
        {
            //accept
            int client_st = server_accept(listen_st);
            if (client_st < 0)
            {
                //继续等待下次客户端连接
                continue;
            }
            //客户端连接成功 设置客户端非阻塞
            setnonblock(client_st);
            //将客户端socket加入socket池中
            for (i = 0; i < MAXSOCKET; i++)
            {
                if (client[i] == -1)
                {
                    client[i] = client_st;
                    break;
                }
            }
            if (i == MAXSOCKET)
            {
                //socket池已满,关闭客户端连接
                close_socket(client_st);
            }
        }
        //处理客户端的socket
        for (i = 0; i < MAXSOCKET; i++)
        {
            if (client[i] == -1)
            {
                //无效socket直接退出
                continue;
            }
            //判断是否是这个socket有事件发生
            if (FD_ISSET(client[i], &allset))
            {
                //接收消息
                if (socket_recv(client[i]) < 0)
                {
                    //如果接收消息出错,关闭客户端socket
                    close_socket(client[i]);
                    //从socket池中将这个socket清除
                    client[i] = -1;
                }
                rc--;
            }
            //说明所有消息的socket已经处理完成
            if (rc < 0)
            {
                //备注:双循环break只能跳出最近的一重循环
                break;
            }
        }
    }
    //close server socket
    close_socket(listen_st);
    return 0;
}
时间: 2024-10-03 22:42:12

Linux 网络编程九(select应用--大并发处理)的相关文章

linux网络编程九:splice函数,高效的零拷贝

from:http://blog.csdn.net/jasonliuvip/article/details/22600569 linux网络编程九:splice函数,高效的零拷贝 最近在看<Linux高性能服务器编程>,在此做个日记,以激励自己,同时分享于有需要的朋友. 1. splice函数 [cpp] view plain copy #include <fcntl.h> ssize_t splice(int fd_in, loff_t *off_in, int fd_out, 

Linux网络编程:select编程基本实现思路

一.打开网络通讯端口,选用TCP协议 listenfd = socket(AF_INET,SOCK_STREAM,0); 二.初始化servaddr,并且进行网络字节序转换 bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family         = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port           = htons(SERV_PO

linux网络编程:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)

从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型: int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout); 所在的头文件为:#include <sys/time.h> 和#include <uni

Linux网络编程——sendfile和splice零拷贝

sendfile和splice零拷贝 sendfile: ? 原始:首先将文件读到内核态的文件描述符中,然后再拷贝给用户态buf,再重新拷贝给内核态中网络缓冲区发给客户端.拷贝2次 ? sendfile是一个接口能直接让文件从内核态的文件描述符送到网络缓冲区从而实现零拷贝 ? 函数原型:ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); ? out_fd为文件描述符,in_fd为网络缓冲区描述符,offset

Linux网络编程 五种I/O 模式及select、epoll方法的理解

Linux网络编程 五种I/O 模式及select.epoll方法的理解 web优化必须了解的原理之I/o的五种模型和web的三种工作模式 五种I/O 模式--阻塞(默认IO模式),非阻塞(常用语管道),I/O多路复用(IO多路复用的应用场景),信号I/O,异步I/OLinux网络编程 五种I/O 模式及select.epoll方法的理解

嵌入式 Linux网络编程(四)——Select机制

嵌入式 Linux网络编程(四)--Select机制 一.select工作机制 poll和select,都是基于内核函数sys_poll实现的,不同在于在linux中select是从BSD Unix系统继承而来,poll则是从SYSTEM V Unix系统继承而来,因此两种方式相差不大.poll函数没有最大文件描述符数量的限制.poll和 select与一样,大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,开销随着文件描述符数量的增加而线性增大. select需要驱动程序的支持,驱动

Linux网络编程入门 (转载)

http://www.cnblogs.com/RascallySnake/archive/2012/01/04/2312564.html (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端        在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序. 比如我们使用ftp程序从另外一        个地方获取文件

Linux网络编程入门

(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍 客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端 在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序. 比如我们使用ftp程序从另外一 个地方获取文件的时候,是我们的ftp程序主动同外面进行通信(获取文件), 所以这个地方我们的ftp程序就是客户端程序. 服务端 和客户端相对应的程序即为服务端程序.被动的等待外面的程序来和自己通

[转] - Linux网络编程 -- 网络知识介绍

(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户端        在网络程序中,如果一个程序主动和外面的程序通信,那么我们把这个程序称为客户端程序. 比如我们使用ftp程序从另外一        个地方获取文件的时候,是我们的ftp程序主动同外面进行通信(获取文件), 所以这个地方我们的ftp程序就是客户端程序. 服务端        和客户端相