练习C之SELECT形式的非阻塞IO

呵呵,理解得不深,但毕竟手打全版,且无错。但select.h不知何处找头文件,

粘下来作个记录。

POLL,EPOLL感觉代码类似,只是函数和系统实现不一样,,EPOLL目前最合理的。定位精确,算法复杂度最好。

#include "select.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>

typedef struct _CLIENT{
    int fd;
    struct sockaddr_in addr;
} CLIENT;

#define MYPORT 59000

#define BACKLOG 5

CLIENT client[BACKLOG];

int currentClient = 0;

#define REVLEN 10
char recvBuf[REVLEN];

void showClient();
int main()
{
    int i, ret, sinSize;
    int recvLen = 0;
    fd_set readfds, writefds;
    int sockListen, sockSvr, sockMax;
    struct timeval timeout;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;

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

    printf("accept started\n");

    //socket
    if ((sockListen = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("socket error\n");
        return -1;
    }

    bzero(&server_addr, sizeof(server_addr));

    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(MYPORT);

    //bind
    if(bind(sockListen, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
    {
        printf("bind error\n");
        return -1;
    }

    //listen
    if(listen(sockListen, 5)< 0)
    {
        print("listen error\n");
        return -1;
    }

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

    //select
    while(1)
    {
        FD_ZERO(&readfds);
        FD_SET(sockListen, &readfds);
        sockMax = sockListen;

        for(i=0; i<BACKLOG; i++)
        {
            if(client[i].fd > 0)
            {
                FD_SET(client[i].fd, &readfds);
                if(sockMax<client[i].fd)
                {
                    sockMax = client[i].fd;
                }
            }
        }

        timeout.tv_sec = 3;
        timeout.tv_usec = 0;

        ret = select((int)sockMax+1, &readfds, NULL, NULL, &timeout);
        if(ret < 0)
        {
            printf("select error\n");
            break;
        }
        else if(ret == 0)
        {
            printf("timeout...\n");
            continue;
        }
        printf("test111\n");

        for(i=0; i<BACKLOG; i++)
        {
            if(client[i].fd>0 && FD_ISSET(client[i].fd, &readfds))
            {
                if(recvLen != REVLEN)
                {
                    while(1)
                    {
                        ret = recv(client[i].fd, (char *)recvBuf+recvLen, REVLEN-recvLen, 0);
                        if(ret == 0)
                        {
                            client[i].fd = -1;
                            recvLen = 0;
                            break;
                        }
                        else if(ret < 0)
                        {
                            client[i].fd = -1;
                            recvLen = 0;
                            break;
                        }

                        recvLen = recvLen + ret;
                        if(recvLen < REVLEN)
                        {
                            continue;
                        }
                        else
                        {
                            printf("%s, buf = %s\n", inet_nota(client[i].addr.sin_addr), recvBuf);
                            recvLen = 0;
                            break;
                        }
                    }
                }
            }
        }

        if(FD_ISSET(sockListen, &readfds))
        {
            printf("isset\n");
            sockSvr = accept(sockListen, NULL, NULL);

            if(sockSvr == -1)
            {
                printf("accept error\n");
            }
            else
            {
                currentClient++;
            }

            for(i=0; i< BACKLOG; i++)
            {
                if(client[i].fd < 0)
                {
                    client[i].fd = sockSvr;
                    client[i].addr = client_addr;
                    printf("You got a connection from %s \n", inet_ntoa(client[i].addr.sin_addr));
                    break;
                }
            }
        }
    }

    printf("test\n");
    return 0;
}

void showClient()
{
    int i;
    printf("client count = %d\n", currentClient);

    for(i=0; i<BACKLOG; i++)
    {
        printf("[%d] = %d", i, client[i].fd);
    }
    printf("\n");
}

 

时间: 2024-10-22 22:13:44

练习C之SELECT形式的非阻塞IO的相关文章

Python异步非阻塞IO多路复用Select/Poll/Epoll使用

来源:http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理还是有必要的. 下面记录下分别基于Select/Poll/Epoll的echo server实现. Python Select Server,可监控事件数量有限制: #!/usr/bin/python # -*- coding: utf-8 -*- import select import sock

非阻塞IO模式原理

与阻塞模式对应的另一种模式叫非阻塞IO模式,在整个通信过程中读和写操作不会阻塞,当前处理线程不存在阻塞情况.从A机器到B机器它的通信过程是:A机器一条线程将通道设置为写事件后往下执行,而另外一条线程遍历到此通道有字节要写并往socket写数据,B机器一条线程遍历到此通道有字节要读,交给另外一条线程对socket读数据,处理完又把通道设置为写事件,遍历线程遍历到此通道有字节要写,又往socket写数据传往A机器,不断往下循环此操作直到完成通信.这个过程每台机器都有两类主要线程,一类是负责逻辑处理且

Tornado Web Server 2.0发布 非阻塞IO的Web服务器软件

Tornado web server 是使用Python编写出来的一个极轻量级.高可伸缩性和非阻塞IO的http://www.aliyun.com/zixun/aggregation/17117.html">Web服务器软件,著名的 Friendfeed 网站就是使用它搭建的. Tornado 跟其他主流的Web服务器框架(主要是Python框架)不同是采用epoll非阻塞IO,响应快速,可处理数千并发连接,特别适用用于实时的Web服务. 要使用它,必须按照以下套件: 1)Python(建

Python中使用select模块实现非阻塞的IO_python

Socket的英文原义是"孔"或"插座".作为BSD UNIX的进程通信机制,取后一种意思.通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.在Internet上的主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务.Socket正如其英文原意那样,像一个多孔插座.一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110

一个高可扩展的基于非阻塞IO的服务器架构

原文链接   译者:mailto:ahahage@163.com 目录 线程体系结构 反应堆模式 组件架构 接收器 分配器 分配器级别事件处理器 应用程序级别事件处理器 总结 参考资料 如果你被要求去写一个高可扩展性的基于JAVA的服务器,你很快就会决定使用JAVA NIO包.为了让服务器跑起来,你可能会花很多时间阅读博客和教程来了解线程同步需要NIO SELECTOR类以及处理一些常见的陷阱.本文描述了一个面向连接基于NIO的服务器的基本架构.本文会先看一下一个首选的线程模型然后讨论服务器的一

Node.js 非阻塞IO和事件循环

非阻塞的IO模型 首先,IO操作无疑是耗时的,当服务器端接收到大量请求时,为每一个请求创建进程或线程的同时,也增加了额外的内存开销,也可能浪费更多的时间资源. 由于Node.js是事件驱动的,于是它使用了事件循环来解决IO操作带来的瓶颈问题.在Node.js中,一个IO操作通常会带有一个回调函数,当IO操作完成并返回时,就会调用这个回调函数,而主线程则继续执行接下来的代码.简单的用一个例子来说明这个问题: request('http://www.google.com', function(err

非阻塞IO服务器模型

我们来考虑一个情形,你跟千千万万个玩家是魔兽世界的超级粉丝,每周末准时组团打boss.每当周末游戏服务器就亚历山大,因为起码几十万用户同时在线.如果用我们的多线程阻塞服务器作为游戏服务器是否可行呢?先分析游戏服务器有哪些特点: ①  网络游戏并非像网页一样,打开一旦下载完就可以关闭连接结束.网游必须是有一个持久有状态的连接,每一个客户端都需要跟服务器存在一个持久的连接,以便快速及时发送消息.而随着并发用户数量的增加,多线程阻塞服务器不可能为每一个客户端分配一个线程. ②  跟一般的应用服务器不同

面向连接的socket数据处理过程以及非阻塞connect问题

对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后必须调用bind绑定到一个指定的地址,然后调用int listen(int sockfd, int backlog);进行监听.此时服务器socket允许客户端进行连接,backlog提示没被accept的客户连接请求队列的大小,系统决定实际的值,最大值定义为SOMAXCONN在头文件<sys/so

关于网络IO中的同步、异步、阻塞、非阻塞

在高并发编程当中,我们经常会遇到一些异步.非阻塞等一些概念,一些常用的技术比如异步的httpclient.netty nio.nginx.node.js等,它们的原理大都跟异步.非阻塞有关.特别是在服务器开发中,并发的请求处理是个大问题,阻塞式的函数会导致资源浪费和时间延迟.通过事件注册.异步函数,开发人员可以提高资源的利用率,性能也会改善.其nginx和node.js处理并发都是采用的事件驱动异步非阻塞模式.其中nginx中处理并发用的是epoll,poll,queue等方式,node.js使