网络编程-IO复用模型-select (7)

在前面章节中讲到了如何利用多进程进行并发tcp通信,由于进程开销大,占用资源多,面对现在的高并发的应用场景,可能同时在线人数都是百万千万级别,不可能一个socket连接就fork一个单独的进程处理,所以多进程来处理多tcp连接情况,了解即可。那是不是也需要采用多线程来处理高并发的情况呢,笔者对此研究不多,如果有大神还请指教,再次猜测一下,估计是利用io复用模型结合多线程来处理吧。
现在学习了解一下select如何使用,首先需要了解几个函数,在linux控制台下面man select可以得到select的相关介绍,简介如下:

       /*
nfds:最大描述符加1
readfds:需要监控的读的描述符集合
writefds:需要监控的写的描述符集合
exceptfds:需要监控的except的描述符的集合
timeout:	超时时间,如果超时时间设置为NULL,则表示阻塞,直到有消息,如果超时时间设置为0,则表示函数立即返回,
*/
       int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
        FD_ZERO(fd_set *fdset) 将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
    FD_SET(fd_set *fdset) 用于在文件描述符集合中增加一个新的文件描述符。
    FD_CLR(fd_set *fdset) 用于在文件描述符集合中删除一个文件描述符。
    FD_ISSET(int fd,fd_set *fdset) 用于测试指定的文件描述符是否在该集合中。
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <resolv.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <fcntl.h>
#include <time.h>

const int MAXBUF = 1024;

const unsigned int MAXACCEPT = 20;
int acceptfd[MAXACCEPT];
int acceptCount = 0;
// 创建tcp监听套接字并设置
int tcpSocket(int port)
{
        int socketfd = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in src;
        src.sin_family = AF_INET;
        src.sin_port = htons(port);
        src.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(src.sin_zero, 0, sizeof(src.sin_zero));
        int ret = 0;
        ret = bind(socketfd, (struct sockaddr *)&src, sizeof(struct sockaddr_in));
        if (ret != 0)
        {
                printf("bind failed ret = %d\n", ret);
                close(socketfd);
                socketfd = 0;
                return 0;
        }
       
        listen(socketfd, 1500);
        printf("listen socket = %d\n", socketfd);
        return socketfd;
}

int main()
{
        
        int serverFD = 0;
        serverFD = tcpSocket(10567);
        memset(acceptfd, 0, sizeof(acceptfd));
		if(acceptfd == 0)
		{
			printf("create listen socket failed\n");
			return -1;
		}
        fd_set set;
        int i = 0;
        int maxSocket = 0;
        struct timeval timeout = {0, 50000};
        clock_t startTime = clock();
        clock_t endTime = clock();
        char buff[MAXBUF] = {0};
        while (1)
        {
        		// 重置监听套接字集合
                FD_ZERO(&set);
				//存储最大套接字
                int socketMax = 0;
               
                FD_SET(serverFD , &set);
               socketMax = (serverFD  > socketMax ? serverFD  : socketMax );
                   
                  // acceptfd数组中存储的已连接的套接字,循环加入到set集合中
                for (int j = 0; j < acceptCount; j++)
                {
                        if (acceptfd[j] != 0)
                        {
                                printf("fdset, j = %d, acceptfd[%d] = %d\n", j, j, acceptfd[j]);
                                FD_SET(acceptfd[j], &set);
                                socketMax = (acceptfd[j] > socketMax ? acceptfd[j] : socketMax );
                        }
                }

                int status = select(socketMax + 1, &set, &set, NULL, NULL);
                if (status == -1)
                {
                        printf("select error = %s\n", strerror(errno));
                        break;
                }
                else if (status == 0)
                {
                        printf("no avaliable data\n");
                        continue;
                }

               // 判断是否可读
                        if(FD_ISSET(serverFD , &set))
                        {
                                //printf("serverFD  = %d\n", j,serverFD );
                                struct sockaddr dst;
                                i++;
                                unsigned int sockaddrLen = sizeof(struct sockaddr);

                                int connectfd = accept(array[j], &dst, &sockaddrLen);
                                if (connectfd < 0)
                                {
                                        //printf("connectfd = %d, error = %s\n", connectfd, strerror(errno));
                                        continue;
                                }
                                acceptfd[acceptCount] = connectfd;

                                acceptCount++;
                                maxSocket++;
                                printf("accept fd = %d, acceptCount = %u, accept Count = %d\n", connectfd, acceptCount, maxSocket);
                        }
                
                for (int j = 0; j < acceptCount; ++j)
                {
                        if (FD_ISSET(acceptfd[j], &set))
                        {
                                //printf("acceptfd[%d] = %d\n", j, acceptfd[j]);
                                struct sockaddr dst;
                                i++;
                                unsigned int sockaddrLen = sizeof(struct sockaddr);

                                memset(buff, 0, sizeof(buff));
                                int ret = recv(acceptfd[j], buff, sizeof(buff), MSG_DONTWAIT);
                                if((ret < 0) && ((errno == EINTR) || (errno == EWOULDBLOCK) || (errno == EAGAIN)))
                                {
                                        continue;
                                }
                                else if(ret > 0)
                                {
                                        printf("socket = %d,recv buff = %s, port = %u\n", acceptfd[j], buff, (*(sockaddr_in *)&dst).sin_port);

                                        memset(buff, 0, sizeof(buff));
                                        memcpy(buff, "hello server", strlen("hello server"));
                                        send(acceptfd[j], buff, sizeof(buff), MSG_DONTWAIT);
                                }
                                else
                                {
                                        close(acceptfd[j]);
                                        printf("close acceptfd[%d] = %d\n", j, acceptfd[j]);
                                        FD_CLR(acceptfd[j], &set);
                                        acceptfd[j] = 0;
                                        maxSocket--;
                                        continue;
                                }

                        }
                }
        }

  close(serverFD);
   serverFD  = 0;                   
        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值