使用poll实现的io多路复用服务端和客户端
http://blog.csdn.net/robertkun/article/details/52269313
参考:http://www.cnblogs.com/Anker/p/3261006.html
使用poll实现的io多路复用服务端和客户端。
客户端通过子进程创建多个客户端连接。
客户端每隔1秒向服务端发送一个时间戳,
服务端接收到时间戳以后,保存在本地的文件中,
一个客户端对应一个存储文件,
并将接收到的时间戳返回给客户端。
代码:
服务端:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <poll.h>
- #include <errno.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #define IP_ADDR "127.0.0.1"
- #define PORT 59999
- #define LISTEN_Q 5
- #define OPEN_MAX 100000
- #define INFTIM -1
- #define MAX_LINE 1024
- static int socket_bind(const char* ip, int port);
- static void do_poll(int ln_fd);
- static void handle_conn(struct pollfd* conn_fds, int num, int* files);
- int main()
- {
- int ln_fd, cn_fd, sk_fd = 0;
- struct sockaddr_in _addr;
- socklen_t _len;
- ln_fd = socket_bind(IP_ADDR, PORT);
- listen(ln_fd, LISTEN_Q);
- do_poll(ln_fd);
- return 0;
- }
- static int socket_bind(const char* ip, int port)
- {
- int ln_fd;
- struct sockaddr_in _addr;
- ln_fd = socket(AF_INET, SOCK_STREAM, 0);
- if(ln_fd == -1) {
- perror("socket error!");
- exit(1);
- }
- bzero(&_addr, sizeof(_addr));
- _addr.sin_family = AF_INET;
- inet_pton(AF_INET, ip, &_addr.sin_addr);
- _addr.sin_port = htons(port);
- if(bind(ln_fd, (struct sockaddr*)&_addr, sizeof(_addr)) == -1) {
- perror("bind error!");
- exit(1);
- }
- return ln_fd;
- }
- static void do_poll(int ln_fd)
- {
- int connfd, sockfd = 0;
- struct sockaddr_in _addr;
- socklen_t _len;
- int files[OPEN_MAX];
- struct pollfd clients[OPEN_MAX];
- int nMax, i, nReady = 0;
- clients[0].fd = ln_fd;
- clients[0].events = POLLIN;
- for(i = 1; i<OPEN_MAX; ++i) {
- clients[i].fd = -1;
- }
- nMax = 0;
- while(1) {
- nReady = poll(clients, nMax+1, INFTIM);
- if(nReady == -1) {
- perror("poll error!");
- exit(1);
- }
- else {
- printf("poll ready num = %d\n", nReady);
- }
- if(clients[0].revents & POLLIN) {
- _len = sizeof(_addr);
- if((connfd = accept(ln_fd, (struct sockaddr*)&_addr, &_len)) == -1) {
- if(errno == EINTR) {
- printf("EINTR!\n");
- continue;
- }
- else {
- perror("accept error!");
- exit(1);
- }
- }
- fprintf(stdout, "accept a new client! [%s]\n", inet_ntoa(_addr.sin_addr));
- for(i=1; i<OPEN_MAX; ++i) {
- if(clients[i].fd < 0) {
- fcntl(connfd, F_SETFL, fcntl(connfd,F_GETFL)| O_NONBLOCK);
- unsigned long nVal=1;
- ioctl(connfd, FIONBIO, &nVal);
- clients[i].fd = connfd;
- char path[2048] = {"\0"};
- getcwd(path, sizeof(path));
- sprintf(path, "%s/tmp_%d.txt", path, i);
- printf("path=%s\n", path);
- int fd = open(path, O_RDWR|O_APPEND|O_CREAT, 0666);
- if(fd > 0) {
- files[i] = fd;
- }
- else {
- fprintf(stdout, "open file error! [%s]\n", path);
- perror("open file error!");
- }
- break;
- }
- }
- fflush(stdout);
- if(i == OPEN_MAX) {
- fprintf(stderr, "too many clients\n");
- exit(1);
- }
- clients[i].events = POLLIN;
- nMax = (i > nMax ? i : nMax);
- if(--nReady <= 0) {
- printf("nReady = %d, nMax = %d\n", nReady, nMax);
- continue;
- }
- }
- handle_conn(clients, nMax, files);
- }
- }
- static void handle_conn(struct pollfd* conn_fds, int num, int* files)
- {
- int i, n = 0;
- char buf[MAX_LINE];
- memset(buf, 0, MAX_LINE);
- for(i=1; i<=num; ++i)
- {
- if(conn_fds[i].fd < 0)
- continue;
- if(conn_fds[i].revents & POLLIN) {
- n = read(conn_fds[i].fd, buf, MAX_LINE);
- if(n == 0) {
- close(conn_fds[i].fd);
- conn_fds[i].fd = -1;
- continue;
- }
- write(files[i], buf, n);
- write(conn_fds[i].fd, buf, n);
- }
- }
- }
客户端:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <poll.h>
- #include <errno.h>
- #include <arpa/inet.h>
- #define MAX_LINE 1024
- #define IP_ADDR "127.0.0.1"
- #define SERV_PORT 59999
- #define max(a,b) (a>b)?a:b
- static void do_conn();
- static void handle_conn(int sockfd);
- int main(int args, char* argv[])
- {
- int i = 0;
- for(i=0; i<2000; ++i) {
- pid_t fpid = -1;
- fpid = fork();
- if(fpid < 0) {
- printf("error in fork!");
- }
- else if(fpid == 0) {
- do_conn();
- }
- else {
- //do_conn();
- }
- }
- return 0;
- }
- static void do_conn()
- {
- int sockfd;
- struct sockaddr_in _addr;
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- bzero(&_addr, sizeof(_addr));
- _addr.sin_family = AF_INET;
- _addr.sin_port = htons(SERV_PORT);
- inet_pton(AF_INET, IP_ADDR, &_addr.sin_addr);
- int ret = connect(sockfd, (struct sockaddr*)&_addr, sizeof(_addr));
- if(ret < 0) {
- perror("connect failed!");
- exit(1);
- }
- handle_conn(sockfd);
- }
- static void handle_conn(int sockfd)
- {
- char send_line[MAX_LINE] = {'\0'};
- char recv_line[MAX_LINE] = {'\0'};
- struct pollfd pfds[1];
- pfds[0].fd = sockfd;
- pfds[0].events = POLLIN|POLLOUT;
- while(1) {
- poll(pfds, 1, 1000);
- if(pfds[0].revents & POLLIN) {
- int ret = read(sockfd, recv_line, MAX_LINE);
- if(ret == 0) {
- perror("client: server is closed.");
- close(sockfd);
- continue;
- }
- else if(ret < 0) {
- perror("client: read error!");
- continue;
- }
- //printf("[%d] recv=%s\n", (int)getpid(), recv_line);
- }
- if(pfds[0].revents & POLLOUT) {
- time_t _time = time(0);
- char dt[20]={"\0"};
- sprintf(dt, "%d\n", _time);
- memcpy(send_line, dt, strlen(dt));
- int ret = write(sockfd, send_line, strlen(send_line));
- if(ret < 0) {
- perror("write error!!");
- }
- }
- sleep(1);
- }
- shutdown(sockfd, SHUT_WR);
- }
使用poll实现的io多路复用服务端和客户端相关推荐
- php io select,Python IO多路复用之——select方案服务端和客户端代码【python源码详解】...
准备文件: IO.py 服务端代码 tcp_c.py 客户端代码 IO.py 代码: from select import * #引入 select 模块 from socket import * ...
- SpringBoot(23) 集成socket.io服务端和客户端实现通信
一.前言 websocket和socket.io区别? websocket 一种让客户端和服务器之间能进行双向实时通信的技术 使用时,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况 适合用于cli ...
- 模拟QQ聊天小项目收尾---界面展示服务端与客户端进行信息交互(用到的知识:io,线程,Swing界面,面向对象思想...... )
大家好,我是一位在java学习圈中不愿意透露姓名并苟且偷生的小学员,如果文章有错误之处,还望海涵,欢迎多多指正 如果你从本文学到有用的干货知识,那么请您尽量点赞,关注,评论,收藏 这两天我一直在设计这 ...
- socket.io服务端是java_SpringBoot(23) 集成socket.io服务端和客户端实现通信
@Slf4j @Service(value = "socketIOService") public class SocketIOServiceImpl implements ISo ...
- web 服务端与客户端交互
Web server to client communication Technology 1. Traditional solution 传统模式的 Web 系统以客户端发出请求.服务器端响应的 ...
- 服务端向客户端主动发送消息
通常情况下,无论是web浏览器还是移动app,我们与服务器之间的交互都是主动的,客户端向服务器端发出请求,然后服务器端返回数据给客户端,客户端浏览器再将信息呈现,客户端与服务端对应的模式是: 客户端请 ...
- 【计算机网络】服务端和客户端最大支持多少tcp连接?如何分析?
文章目录 (一)引用文章 (二)简单分析: 1.基本概念:TCP四元组 2.多个客户端连接一个服务端最大支持最大多少tcp连接? 3.一个客户端连接一个服务端最大支持多少个tcp连接? (二)全面分析 ...
- java sslsocket程序_JAVA与C++进行sslsocket通信,JAVA做服务端或客户端
前几天有位网友问我关于Unity3D里面使用Protobuf的方法,一时有事拖到现在才写这篇文章,不好意思哈. 本文测试环境: 系统:WINDOWS 7(第3.6步).OS X 10.9(第4步) 软 ...
- netty tcp服务端主动断开客户端_【Netty】服务端和客户端
欢迎关注公众号:[爱编程] 如果有需要后台回复2019赠送1T的学习资料哦!! 本文是基于Netty4.1.36进行分析 服务端 Netty服务端的启动代码基本都是如下: private void s ...
最新文章
- android里面画布快照,自定义 View - Canvas - 画布操作和快照
- 解决IE6下 position的fixed定位问题
- UI调试--初步尝试心得总结
- Web应用进行XSS漏洞测试
- oracle100多g满了,Oracle11g ORA-00257归档日志满问题处理
- 如何设置word的有效期
- mini6410 LED驱动程序及LED测试程序的设计
- 电脑桌面有计算机和回收站怎么办,电脑回收站不见了怎么办 电脑回收站找回的4种方法...
- KALI2021安装teemo的一些问题
- IT人的求职技巧 中山大学新炬网络校园宣讲会
- Chrome浏览器怎么安装插件
- php-cli和php-fpm的关系是什么?
- 攻防世界007 伪造xff_referer
- Java软件工程师[初级测试题]
- 百度地图经纬度与腾讯地图经纬度之间的转换
- python tcp黏包和struct模块解决方法,大文件传输方法及MD5校验
- Win10任务栏重启无数次都在转圈卡死解决方法(超级简单)
- form表单如何加css框架,如何写好CSS系列之表单(form)
- Compound-Fault Diagnosis of Rotating Machinery: A Fused Imbalance Learning Method
- 世界500强企业优秀员工的十二条核心标准
热门文章
- 以A表中的值快速更新B表中记录的方法
- Hive中的数据库、表、数据与HDFS的对应关系
- iframe高度自适应,终于解决了
- java 获取随机数字的三种方法
- 将 JAR 转为 EXE – JSMOOTH 的使用教程(第二期)(转载)
- hdu--4902--线段树
- linux 命令案例学习——文件搜索
- 端口如何支持非localhost访问_新特性解读 | MySQL 8.0.19 支持 DNS SRV
- 自动论文生成器 python_Python生成器常见问题及解决方案
- 不存在_施文忠 | ”存在“与“不存在”——巴蜀文明概论