Linux select 实现并发服务器和客户端
转载:http://blog.csdn.net/szkbsgy/article/details/10558881
- <span style="font-size:18px;">服务端:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/select.h>
- #include <errno.h>
- #define SERVER_IP "127.0.0.1"
- #define SERVER_PORT 8000
- #define MAX_RECV_LEN 1024
- #define MAX_CLIENT_NUM 30
- #define BACK_LOG 20
- static int running = 1;
- int main(int argc, char *argv[])
- {
- int sock_fd = -1;
- int ret = -1;
- struct sockaddr_in serv_addr;
- struct sockaddr_in cli_addr;
- socklen_t serv_addr_len = 0;
- socklen_t cli_addr_len = 0;
- int client_fd[MAX_CLIENT_NUM];
- char recv_buf[MAX_RECV_LEN];
- int new_conn_fd = -1;
- int i = 0;
- int max_fd = -1;
- int num = -1;
- struct timeval timeout;
- fd_set read_set;
- fd_set write_set;
- fd_set select_read_set;
- FD_ZERO(&read_set);
- FD_ZERO(&write_set);
- FD_ZERO(&select_read_set);
- for (i = 0; i < MAX_CLIENT_NUM; i++)
- {
- client_fd[i] = -1;
- }
- memset(&serv_addr, 0, sizeof(serv_addr));
- memset(&cli_addr, 0, sizeof(cli_addr));
- sock_fd = socket(AF_INET, SOCK_STREAM, 0);
- if (sock_fd < 0)
- {
- perror("Fail to socket");
- exit(1);
- }
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(SERVER_PORT);
- serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
- unsigned int value = 1;
- if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
- (void *)&value, sizeof(value)) < 0)
- {
- perror("Fail to setsockopt");
- exit(1);
- }
- serv_addr_len = sizeof(serv_addr);
- if (bind(sock_fd, (struct sockaddr*)&serv_addr, serv_addr_len) < 0)
- {
- perror("Fail to bind");
- exit(1);
- }
- if (listen(sock_fd, BACK_LOG) < 0)
- {
- perror("Fail to listen");
- exit(1);
- }
- char buf[1024];
- max_fd = sock_fd;
- int len;
- FD_SET(sock_fd, &read_set);
- while (running)
- {
- timeout.tv_sec = 5;
- timeout.tv_usec = 0;
- max_fd = sock_fd;
- for (i = 0; i < MAX_CLIENT_NUM; i++)
- {
- if (max_fd < client_fd[i])
- {
- max_fd = client_fd[i];
- }
- }
- select_read_set = read_set;
- ret = select(max_fd + 1, &select_read_set, NULL, NULL, &timeout);
- if (ret == 0)
- {
- printf("timeout\n");
- }
- else if (ret < 0)
- {
- printf("error occur\n");
- }
- else
- {
- if (FD_ISSET(sock_fd, &select_read_set))
- {
- printf("new client comes\n");
- len = sizeof(cli_addr);
- new_conn_fd = accept(sock_fd, (struct sockaddr*)&cli_addr, &len);
- if (new_conn_fd < 0)
- {
- perror("Fail to accept");
- exit(1);
- }
- else
- {
- for (i = 0; i < MAX_CLIENT_NUM; i++)
- {
- if (client_fd[i] == -1)
- {
- client_fd[i] = new_conn_fd;
- FD_SET(new_conn_fd, &read_set);
- break;
- }
- if (max_fd < new_conn_fd)
- {
- max_fd = new_conn_fd;
- }
- }
- }
- }
- else
- {
- for (i = 0; i < MAX_CLIENT_NUM; i++)
- {
- if (-1 == client_fd[i]) {
- continue;
- }
- memset(recv_buf, 0, MAX_RECV_LEN);
- if (FD_ISSET(client_fd[i], &select_read_set))
- {
- num = read(client_fd[i], recv_buf, MAX_RECV_LEN);
- if (num < 0)
- {
- printf("Client(%d) left\n", client_fd[i]);
- FD_CLR(client_fd[i], &read_set);
- close(client_fd[i]);
- client_fd[i] = -1;
- }
- else if (num > 0)
- {
- recv_buf[num] = '\0';
- printf("Recieve client(%d) data\n", client_fd[i]);
- printf("Data: %s\n\n", recv_buf);
- } if (num == 0)
- {
- printf("Client(%d) exit\n", client_fd[i]);
- FD_CLR(client_fd[i], &read_set);
- close(client_fd[i]);
- client_fd[i] = -1;
- }
- }
- }
- }
- }
- }
- return 0;
- }
- 客户端:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/select.h>
- #define SERVER_IP "127.0.0.1"
- #define SERVER_PORT 8000
- #define MAX_RECV_LEN 1024
- static int running = 1;
- int main(int argc, char *argv[])
- {
- int sock_fd = -1;
- int ret = -1;
- struct sockaddr_in serv_addr;
- struct sockaddr_in cli_addr;
- socklen_t serv_addr_len = 0;
- memset(&serv_addr, 0, sizeof(serv_addr));
- sock_fd = socket(AF_INET, SOCK_STREAM, 0);
- if (sock_fd < 0)
- {
- perror("Fail to socket");
- exit(1);
- }
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(SERVER_PORT);
- serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
- serv_addr_len = sizeof(serv_addr);
- if (connect(sock_fd, (struct sockaddr *)&serv_addr, serv_addr_len) < 0)
- {
- perror("Fail to connect");
- exit(1);
- }
- char buf[1024];
- int num = 0;
- while (running)
- {
- num = read(STDIN_FILENO, buf, MAX_RECV_LEN);
- if (num > 0)
- {
- buf[num] = '\0';
- printf("buf: %s\n", buf);
- num = write(sock_fd, buf, num);
- if (num < 0)
- {
- printf("write failed\n");
- exit(1);
- }
- if (strncmp(buf, "exit", strlen("exit")) == 0)
- {
- printf("Client exit\n");
- close(sock_fd);
- return 0;
- }
- }
- }
- return 0;
- } </span>
- 顶
- 0
- 踩
Linux select 实现并发服务器和客户端相关推荐
- Linux select TCP并发服务器与客户端编程
介绍:运行在ubuntu linux系统,需要先打开一个终端运行服务端代码,这时,可以打开多个终端同时运行多个客户端代码(注意客户端数目要小于MAX_FD);在客户端输入数据后回车,可以看见服务器收到 ...
- 1 linux下tcp并发服务器的几种设计的模式套路,Linux下几种并发服务器的实现模式(详解)...
1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循 ...
- Linux 网络编程——并发服务器的三种实现模型
服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有循环服务器和并发服务器. 循环服务器与并发服务器模型 在网络程序里面,一般来说都是许多客户对应一个服务器(多 ...
- alma linux 上配置 ntp 服务器和客户端
目录 配置 NTP 服务器 1.Chrony 是默认的 NTP 客户端以及RHEL和 AlmaLinux 上的 NTP 服务器 2.使 chrony 服务在系统启动时自动启动 3.由于 chrony ...
- go语言实现tcp并发服务器与客户端
go语言实现tcp并发服务器端与客户端 server.go // nc 连接, 发送字母, 加收到转大写的字母 // 如果发送exit ,则会断开连接 package mainimport (&quo ...
- epoll ET模式服务器和客户端源码例子
关于epoll替代select作为高性能服务器的事件通知机制的资料相当多,我就不在这里班门弄斧了,有兴趣的同学可以参考末尾的文献链接. 这里说明如下: 1.epoll是linux下高并发服务器的完美方 ...
- 网络编程实战之高级篇, 彻底解决面试C10k问题, 高并发服务器, IO多路复用, 同时监视多个IO事件
目录 一.前言 二.IO多路复用的理解 三.IO多路复用的发展 select poll epoll 四.C10K服务端代码 五. 总结 一.前言 网络入门篇,从操作系统的层次推开网络大门 网络入门基 ...
- linux多进程网络实例,Linux下一个单进程并发服务器的实例 使用select
/*单进程并发服务器实例.该程序采用单进程并发服务器算法实现的.*/ #include #include #include #include #include #include #include #i ...
- 【Linux网络编程】并发服务器的三种实现模型
服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有循环服务器和并发服务器. 循环服务器与并发服务器模型 在网络程序里面,一般来说都是许多客户对应一个服务器(多 ...
最新文章
- html 文本框 无法输入,无法在HTML文本框中输入任何东西
- XCTF-MISC-新手区-gif
- 强悍的命令行 —— echo、env($PATH)、sudo
- Ionic开发App中重要的部分
- 5.hbase表新增数据同步之add_peer
- 导入导出mysql数据库
- 中美线径对照表_美标线径与国标对照及导线介绍
- SkeyePlayer RTSP/RTMP低延迟播放器源码解析系列之效率优化方案
- 使用Python的pandas库操作Excel
- 地球经纬度转换为unity球面坐标
- K8S从入门到放弃系列-(14)Kubernetes集群Dashboard部署
- 1:0 本立而道生!
- Python打印简单杨辉三角形
- 完美删除Mac Os自带输入法
- Linux下挂载NTFS分区
- 图片加水印的简单方法
- 计算机网络:从物理层到应用层的五层模型
- @Cacheable和@CachePut区别
- C#控件之Windows Media Player简单加载视频播放
- 【R语言】ggplot2---散点图的边框和颜色填充问题
热门文章
- node源码详解(五)
- Hibernate 基础配置及常用功能(二)
- 32位系统win2008+mssql2008 6G内存折腾纪实
- 判断滚动条是否到达页面的尾部
- 谈谈C#的私有成员的一个有趣的现象!
- EMF的一些总结(2)——关于EMF的序列化
- python后台开发知识点_面试总结:鹅厂Linux后台开发面试笔试C++知识点参考笔记...
- 一年中所有节日的排列顺序_计数问题(二)-排列组合的使用
- php put 参数,php – 如何在Guzzle 5中发送PUT请求的参数?
- Java是先难后易吗_在解决问题的时候,是先难后易还是先易后难?