Linux IO多路复用之epoll网络编程基本代码-程序员宅基地

技术标签: python  epoll  

server端:

#include  <unistd.h>
#include  <sys/types.h>       /* basic system data types */
#include  <sys/socket.h>      /* basic socket definitions */
#include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include  <arpa/inet.h>       /* inet(3) functions */
#include <sys/epoll.h> /* epoll function */
#include <fcntl.h>     /* nonblocking */
#include <sys/resource.h> /*setrlimit */

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>



#define MAXEPOLLSIZE 10000
#define MAXLINE 10240
int handle(int connfd);
int setnonblocking(int sockfd)
{
    if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {
        return -1;
    }
    return 0;
}

int main(int argc, char **argv)
{
    int  servPort = 6888;
    int listenq = 1024;

    int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0;
    struct sockaddr_in servaddr, cliaddr;
    socklen_t socklen = sizeof(struct sockaddr_in);
    struct epoll_event ev;
    struct epoll_event events[MAXEPOLLSIZE];
    struct rlimit rt;
    char buf[MAXLINE];

    /* 设置每个进程允许打开的最大文件数 */
    rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
    if (setrlimit(RLIMIT_NOFILE, &rt) == -1) 
    {
        perror("setrlimit error");
        return -1;
    }


    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
    servaddr.sin_port = htons (servPort);

    listenfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (listenfd == -1) {
        perror("can't create socket file");
        return -1;
    }

    int opt = 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    if (setnonblocking(listenfd) < 0) {
        perror("setnonblock error");
    }

    if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) 
    {
        perror("bind error");
        return -1;
    } 
    if (listen(listenfd, listenq) == -1) 
    {
        perror("listen error");
        return -1;
    }
    /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */
    kdpfd = epoll_create(MAXEPOLLSIZE);
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = listenfd;
    if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) 
    {
        fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd);
        return -1;
    }
    curfds = 1;

    printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq);

    for (;;) {
        /* 等待有事件发生 */
        nfds = epoll_wait(kdpfd, events, curfds, -1);
        if (nfds == -1)
        {
            perror("epoll_wait");
            continue;
        }
        /* 处理所有事件 */
        for (n = 0; n < nfds; ++n)
        {
            if (events[n].data.fd == listenfd) 
            {
                connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen);
                if (connfd < 0) 
                {
                    perror("accept error");
                    continue;
                }

                sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
                printf("%d:%s", ++acceptCount, buf);

                if (curfds >= MAXEPOLLSIZE) {
                    fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE);
                    close(connfd);
                    continue;
                } 
                if (setnonblocking(connfd) < 0) {
                    perror("setnonblocking error");
                }
                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = connfd;
                if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0)
                {
                    fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno));
                    return -1;
                }
                curfds++;
                continue;
            } 
            // 处理客户端请求
            if (handle(events[n].data.fd) < 0) {
                epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);
                curfds--;


            }
        }
    }
    close(listenfd);
    return 0;
}
int handle(int connfd) {
    int nread;
    char buf[MAXLINE];
    nread = read(connfd, buf, MAXLINE);//读取客户端socket流

    if (nread == 0) {
        printf("client close the connection\n");
        close(connfd);
        return -1;
    } 
    if (nread < 0) {
        perror("read error");
        close(connfd);
        return -1;
    }    
    write(connfd, buf, nread);//响应客户端  
    return 0;
}

 

client端:

#include  <unistd.h>
#include  <sys/types.h>       /* basic system data types */
#include  <sys/socket.h>      /* basic socket definitions */
#include  <netinet/in.h>      /* sockaddr_in{} and other Internet defns */
#include  <arpa/inet.h>       /* inet(3) functions */
#include <sys/select.h>       /* select function*/

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#define MAXLINE 10240
#define max(a,b)    ((a) > (b) ? (a) : (b))
//typedef struct sockaddr  SA;

void handle(int sockfd);

int main(int argc, char **argv)
{
    char * servInetAddr = "127.0.0.1";
    int servPort = 6888;
    char buf[MAXLINE];
    int connfd;
    struct sockaddr_in servaddr;

    if (argc == 2) {
        servInetAddr = argv[1];
    }
    if (argc == 3) {
        servInetAddr = argv[1];
        servPort = atoi(argv[2]);
    }
    if (argc > 3) {
        printf("usage: selectechoclient <IPaddress> <Port>\n");
        return -1;
    }

    connfd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(servPort);
    inet_pton(AF_INET, servInetAddr, &servaddr.sin_addr);
    
    if (connect(connfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        perror("connect error");
        return -1;
    }
    printf("welcome to selectechoclient\n");
    handle(connfd);     /* do it all */
    close(connfd);
    printf("exit\n");
    exit(0);
}


void handle(int connfd)
{
    FILE* fp = stdin;
    char sendline[MAXLINE], recvline[MAXLINE];
    fd_set rset;
    FD_ZERO(&rset);
    int maxfds = max(fileno(fp), connfd) + 1;
    int nread;
    for (;;) {
        FD_SET(fileno(fp), &rset);
        FD_SET(connfd, &rset);

        if (select(maxfds, &rset, NULL, NULL, NULL) == -1) {
            perror("select error");
            continue;
        }

        if (FD_ISSET(connfd, &rset)) {
            //接收到服务器响应
            nread = read(connfd, recvline, MAXLINE);
            if (nread == 0) {
                printf("server close the connection\n");
                break;
            } 
            else if (nread == -1) {
                perror("read error");
                break;    
            }
            else {
                //server response
                write(STDOUT_FILENO, recvline, nread);    
            }  
        }

        if (FD_ISSET(fileno(fp), &rset)) {
            //标准输入可读
            if (fgets(sendline, MAXLINE, fp) == NULL) {
                //eof exit
                break;   
            } 
            else {
                write(connfd, sendline, strlen(sendline));  
            }
        }

    } 
}

 

转载于:https://my.oschina.net/moodlxs/blog/801973

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_33819479/article/details/91909826

智能推荐

Git使用 tortoisegit使用_gittortoise deploy-程序员宅基地

文章浏览阅读607次。参考:http://developer.baidu.com/wiki/index.php?title=docs/cplat/bae/deploy#.E4.BB.A3.E7.A0.81.E5.8F.91.E5.B8.83http://developer.baidu.com/wiki/index.php?title=docs/cplat/rt/manage/git#Git.E5.AE.A2.E6._gittortoise deploy

Manjaro Linux--- 安装引导器_install grub for manjaro-程序员宅基地

文章浏览阅读2.3k次。--- 安装引导器--- --------------------------- GRUB BIOS: # pacman -S grub os-prober# grub-install --recheck /dev/&lt;目标磁盘&gt;# grub-mkconfig -o /boot/grub/grub.cfg UEFI:---如果BIO..._install grub for manjaro

ERROR 1142 CREATE command denied to user 'root'@'xxxxx-程序员宅基地

文章浏览阅读8.8k次。mysql>grant all on . to root@’%’ identified by ‘密码’;mysql>flush privileges;_create command denied to user 'root

神策数据埋点_神策埋点文档-程序员宅基地

文章浏览阅读3.4k次。转载作者:韩girl链接:https://www.jianshu.com/p/1fa6ec85633d来源:简书官方文档 附上:https://manual.sensorsdata.cn/sa/latest/page-1573907.html毕竟才疏学浅,就会那么点东西,以便我下次巩固记忆使用 特写此文章....如果你的项目里面需要前端埋点的看过来首先你需要在你的项目里面下载 sa-sdk-javascript 此插件main.js 引入 import sensors from'sa_神策埋点文档

五款在线思维导图工具的比较_process on跟百度脑图有什么区别-程序员宅基地

文章浏览阅读1.2w次,点赞2次,收藏10次。五款在线思维导图工具对比:MindMaster平台较全的思维导图工具,但是我知道你既然选在线产品,那肯定就不会去下其他平台的软件了,但是顺便一提,他们的电脑版的头脑风暴还不错,有这个需求的可以体验一下。说回在线版,个人评价就是功能较齐全,界面清新简洁,画出来的图较漂亮。免费情况下,可以用的主题较少,悄悄告诉你,你可以自己搭配啊,自己创作的成就感更好。Mindline打开网页发现..._process on跟百度脑图有什么区别

PyQt5 技术篇-QWidget、QDialog程序窗口关闭closeEvent()触发事件方法重写_pyqt qtwidgts closeevent-程序员宅基地

文章浏览阅读1.6w次,点赞8次,收藏33次。PyQt5 技术篇-QWidget、QDialog程序窗口关闭closeEvent()触发事件方法重写。我用 QWidget 来做个示例,它在程序窗口关闭时会触发 closeEvent() 事件,我们把它重写后就能实现关闭窗口时触发我们想要的效果。重点就两个,如下所示:重点一: 重写组件的 closeEvent() 方法。重点二: 主窗口继承重写的组件。_pyqt qtwidgts closeevent

随便推点

Openstack--使用packstack工具一键部署OpenStack_packstack部署openstack-程序员宅基地

文章浏览阅读6.6k次,点赞10次,收藏72次。Openstack----(线网源)使用packstack工具一键部署OpenStack!文章目录Openstack----(线网源)使用packstack工具一键部署OpenStack!一:部署 OpenStack1.1 环境1.2 安装虚拟机1.2.1 IP地址配置与修改主机名1.2.2 初始化操作1.3 一键部署部署OpenStack二、网页登陆OpenStack一:部署 OpenStack1.1 环境VMware软件CentOS7.6最小化安装NAT的IP地址:20.0.0.10pac_packstack部署openstack

Generalplus公司的GP329730A_gp329733a-程序员宅基地

文章浏览阅读603次。最近用了Generalplus公司的GP329730A,与之前的STM32不同,这是一款ARM9核心的芯片欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。新的改变我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Mar..._gp329733a

idea报错:java.lang.UnsatisfiedLinkError: Could not load library. Reasons: [no leveldbjni64-1.8 in java-程序员宅基地

文章浏览阅读3.3k次。java.lang.UnsatisfiedLinkError: Could not load library. Reasons: [no leveldbjni64-1.8 in java.library.path, no leveldbjni-1.8 in java.library.path, C:\Windows\System32\leveldbjni.dll: Can't find depen..._could not load library. reasons: [no leveldbjni64-1.8 in java.library.path,

GNU C __attribute__ 机制简介_c attribute-程序员宅基地

文章浏览阅读646次。GNU C __attribute__ 机制简介 2006-06-17 13:54:00 标签:   [推送到技术圈] 摘要:在学习linux内核代码及一些开源软件的源码(如:DirectFB),经常可以看到有关__attribute__的相关使用。本文结合自己的学习经历,较为详细的介绍了__attribute__相关语法及其使用。-----------_c attribute

CentOS之间rsync做文件增量(备份)同步-程序员宅基地

文章浏览阅读1.9k次。服务器192.168.0.248:本地服务器47.56.34.2:远程服务器目的将远程服务器数据同步到本地服务器前提两台服务器安装rsync和crontabsyum install -y rsyncyum install -y crontabs设置免密登陆在本地服务器..._centos rsync 增量

【Node.js】深度解析搭建后台服务器-http模块_node.js http深度解析-程序员宅基地

文章浏览阅读2.8w次,点赞65次,收藏71次。http 模块是 Node.js 官方提供的、用来创建 web 服务器的模块。通过 http 模块提供的方法,就能方便的把一台普通的电脑,变成一台 Web 服务器,从而对外提供 Web 资源服务。在 Node.js 中,我们不需要使用Apache等这些第三方 web 服务器软件。因为我们可以基于 Node.js 提供的 http 模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供 web 服务。_node.js http深度解析

推荐文章

热门文章

相关标签