Linux下socket通信和epoll
上一篇博客用多线程实现服务端和多个客户端的通信,但是在实际应用中如果服务端有高并发的需求,多线程并不是一个好选择。
实现高并发的一种方法是IO多路复用,也就是select,poll,epoll等等。
于是我采用epoll再修改了服务端,实现单线程服务多个客户端。
服务端:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> // open function
#include <unistd.h> // close function
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/epoll.h> const int PORT = ;
/*
listen_loop(): epoll监听套接字,作不同处理
accept_conn(): 新的客户端连接进来,执行accept,将fd加入epoll set
recv_message(): recv并且重复输出一份给客户端
*/
void listen_loop();
void accept_conn(unsigned int sock_fd, unsigned int epollfd);
void recv_message(unsigned int sock_fd); int main(void) {
int sock_fd;
struct sockaddr_in server_addr; //初始化socket
sock_fd = socket(AF_INET, SOCK_STREAM, );
if (sock_fd < ) {
perror("socket:");
return ;
} //编辑地址
memset(&server_addr, , sizeof(server_addr));
server_addr.sin_family = AF_INET;//ipv_4
server_addr.sin_port = htons(PORT);//监听端口8888
server_addr.sin_addr.s_addr = INADDR_ANY;//本地的任意地址 //绑定然后监听
if (bind(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < ) {
perror("bind:");
return ;
}
if (listen(sock_fd, ) < ) {
perror("listen");
return ;
} listen_loop(sock_fd); return ;
}
void accept_conn(unsigned int sock_fd, unsigned int epollfd) {
struct sockaddr_in clientaddr;
struct epoll_event event;
socklen_t len = sizeof(struct sockaddr);
int accept_fd = ; accept_fd = accept(sock_fd, (struct sockaddr*)&clientaddr, &len); if (accept_fd <= ) {
perror("accept error");
return;
} //将新建连接加入epoll set
event.data.fd = accept_fd;
event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
epoll_ctl(epollfd, EPOLL_CTL_ADD, accept_fd, &event);
return;
} void recv_message(unsigned int sock_fd) {
char recv_buf[], send_buf[]; memset(recv_buf, , sizeof(recv_buf));
memset(send_buf, , sizeof(send_buf)); recv(sock_fd, recv_buf, sizeof(recv_buf), );
fputs(recv_buf, stdout);
strcpy(send_buf, recv_buf);
send(sock_fd, send_buf, sizeof(send_buf), ); return;
}
void listen_loop(unsigned int sock_fd)
{
int epollfd, i, ret;
int timeout = ;
struct epoll_event event;
struct epoll_event eventList[]; /*创建epoll监听事件*/
epollfd = epoll_create();
event.events = EPOLLIN | EPOLLET;
event.data.fd = sock_fd; /*注册epoll监听事件.*/
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock_fd, &event) < ) {
printf("register epoll event err !");
return;
} while () {
ret = epoll_wait(epollfd, eventList, , timeout); /*epoll事件错误.*/
if (ret < ) {
printf("epoll event err!");
break;
}
/*无事件返回.*/
else if (ret == ) {
continue;
} /*epoll返回事件.*/
for (i = ; i < ret; i++) {
/*epoll 错误*/
if ((eventList[i].events & EPOLLERR) || (eventList[i].events & EPOLLHUP) || !(eventList[i].events & EPOLLIN)) {
printf("epoll error\n");
close(eventList[i].data.fd);
exit(-);
} //half connection
if (eventList[i].events & EPOLLRDHUP) {
printf("//one client close the conne.//\n");
close(eventList[i].data.fd);
} /*accept事件*/
if (eventList[i].data.fd == sock_fd) {
accept_conn(sock_fd, epollfd);
}
/*非sock_fd则为其他事件.*/
else {
recv_message(eventList[i].data.fd);
}
}
}
close(epollfd);
close(sock_fd);
return;
}
Linux下socket通信和epoll的更多相关文章
- Linux 下socket通信终极指南(附TCP、UDP完整代码)
linux下用socket通信,有TCP.UDP两种协议,网上的很多教程把两个混在了一起,或者只讲其中一种.现在我把自己这两天研究的成果汇总下来,写了一个完整的,适合初学者参考,也方便自己以后查阅. ...
- Linux下socket通信和多线程
服务端socket流程:socket() –> bind() –> listen() –> accept() –> 读取.发送信息(recv,send等) 客户端socket流 ...
- (8)Linux(客户端)和Windows(服务端)下socket通信实例
Linux(客户端)和Windows(服务端)下socket通信实例: (1)首先是Windows做客户端,Linux做服务端的程序 Windows Client端 #include <st ...
- Linux下进程通信的八种方法
Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量 ...
- linux下socket编程实例
linux下socket编程实例一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.s ...
- (转)Linux下select, poll和epoll IO模型的详解
Linux下select, poll和epoll IO模型的详解 原文:http://blog.csdn.net/tianmohust/article/details/6677985 一).Epoll ...
- Linux下Socket编程的端口问题( Bind error: Address already in use )
Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误 ...
- linux下串口通信与管理
linux下的串口与windows有一些区别,下面将介绍一下linux下串口通信管理 查看是否支持USB串口: #lsmod | grep usbserial 如果没有信息:sudo apt-get ...
- UNIX下socket通信 - UDP通信
一.UNIX下socket通信: socket套接字是一种可以进行网络通信的内核对象,它是一个唯一的标示符,一般称它为socket描述符. 注意:UDP通信需要客户端先发送消息,服务端先进行等待客户端 ...
随机推荐
- Ubuntu18.04 - 返回到Gnome经典桌面!
Ubuntu18.04默认的桌面是定制版的Gnome,说实话,真的不喜欢,还是喜欢Gnome的经典桌面,那么如何进入呢?执行下面命令,执行完毕后注销,选择一下就可以了! sudo apt-get in ...
- python 带参与不带参装饰器的使用与流程分析/什么是装饰器/装饰器使用注意事项
一.什么是装饰器 装饰器是用来给函数动态的添加功能的一种技术,属于一种语法糖.通俗一点讲就是:在不会影响原有函数的功能基础上,在原有函数的执行过程中额外的添加上另外一段处理逻辑 二.装饰器功能实现的技 ...
- 80端口被系统进程PID-4占用解决办法
今天因为工程需要就把tomcat服务器的端口改成了80了,可是一启动就出现问题了 发现报错信息是端口占用了,于是我马上就在了命令行敲入了netstat -ano查看端口占用情况 终于发现是PID为4的 ...
- zoj4019 Schrödinger's Knapsack(dp)
题意:有两种物品分别为n,m个,每种物品对应价值k1,k2.有一个容量为c的背包,每次将一个物品放入背包所获取的价值为k1/k2*放入物品后的剩余体积.求问所获取的最大价值. 整体来看,优先放入体积较 ...
- 浅谈对MVC的认识
MVC是model(模型),view(视图),Controller(控制)的缩写. 模型层负责提供数据,和数据库相关的操作都交给模型层处理: 视图层提供交互的界面,其输出数据: 控制层负责接收各种请求 ...
- 初中级web前端工程师的面试题分享
1.html三栏布局有几种(就是左右固定,中间自适应) 浮动布局float.定位布局.flex布局.表格布局.css3栅栏布局 <style media="screen"&g ...
- 使用.net core读取Json文件配置
1.使用vs2017创建一个应用台程序 2.使用程序包管理器控制台执行命令 Install-Package Microsoft.AspNetCore -Version 2.0.1 3.创建一个json ...
- 【数组】Jump Game
题目: Given an array of non-negative integers, you are initially positioned at the first index of the ...
- 前端通信:ajax设计方案(三)--- 集成ajax上传技术
在此之前让我感慨一下现在的前端开发的氛围.我遇到好多人,给我的观念都是,这个东西这个框架有了,那个东西那个框架做了,前端嘛,学几个框架,这个拼凑一下那个拼凑一下就好了.其实我想问,东西都框架做了,那你 ...
- Python的Mysql操作
网上好多的帖子感觉比较老了,而且千篇一律.我到mysql看了一下官网上python驱动的操作,发现与大部分网站说的都不一样. 首先安装的驱动是: pip install mysql-connector ...