【Socket】linux网络多路复用IO技术
1.mystery引入
2)低级socket程序中有一个共同点:都是基于阻塞式的编程方式
3)非阻塞式是函数调用时不阻塞,不管函数执行成功与否,都会立即返回。
4)优点:程序效率提升
5)缺点:返回的结果往往是错误的类型码
6)解决方案:Select机制。
2.实例操作
1)基于Select模式实现一个网络echo的服务程序,即客户端向服务端发送信息,服务器接收到信息后,再将信息原样转发给客户端
2)需要设置Select函数
3)若当前有新连接,则加入到客户端套接字集合,若数量过载,则断开本次连接,并发送提示信息:sorry overload
4)源代码
//selectsocket.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SERVER_PORT 5555
#define QUEUE_LENGTH 5
#define BUF_SIZE 200
int main(void)
{
int server_socket, new_socket;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t sin_size;
int client_socket[QUEUE_LENGTH];
int conn_num;
int yes = 1;
char buf[BUF_SIZE];
int ret;
int i;
if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
return 0;
}
if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("setsockopt");
return 0;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero));
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
{
perror("bind");
return 0;
}
if (listen(server_socket, 5) == -1)
{
perror("listen");
return 0;
}
printf("listen port %d\n", SERVER_PORT);
fd_set clientfdset;
int maxsock;
struct timeval tv;
conn_num = 0;
sin_size = sizeof(client_addr);
maxsock = server_socket;
while (1)
{
// initialize file descriptor set
FD_ZERO(&clientfdset);
FD_SET(server_socket, &clientfdset);
// timeout setting
tv.tv_sec = 15;
tv.tv_usec = 0;
// add active connection to fd set
for (i = 0; i < QUEUE_LENGTH; i++)
{
if (client_socket[i] != 0)
{
FD_SET(client_socket[i], &clientfdset);
}
}
ret = select(maxsock + 1, &clientfdset, NULL, NULL, &tv);
if (ret < 0)
{
perror("select");
break;
}
else if (ret == 0)
{
printf("waitting timeout\n");
continue;
}
// check every fd in the set
for (i = 0; i < conn_num; i++)
{
if (FD_ISSET(client_socket[i], &clientfdset))
{
ret = recv(client_socket[i], buf, sizeof(buf), 0);
if (ret <= 0)
{
printf("client[%d] close\n", i);
close(client_socket[i]);
FD_CLR(client_socket[i], &clientfdset);
client_socket[i] = 0;
}
else
{
printf("Client[%d] msg:%s\n", i, buf);
send(client_socket[i], buf, sizeof(buf), 0);
}
}
}
if (FD_ISSET(server_socket, &clientfdset))
{
new_socket = accept(server_socket, (struct sockaddr *)&client_addr, &sin_size);
if (new_socket <= 0)
{
perror("accept");
continue;
}
if (conn_num < QUEUE_LENGTH)
{
client_socket[conn_num++] = new_socket;
printf("new client[%d] %s:%d\n", conn_num,
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if (new_socket > maxsock)
maxsock = new_socket;
}
else
{
send(new_socket, "sorry overload!", sizeof("sorry overload!"), 0);
close(new_socket);
break;
}
}
}
for (i = 0; i < QUEUE_LENGTH; i++)
{
if (client_socket[i] != 0)
{
close(client_socket[i]);
}
}
}
3.mystery注解
1)设置高级socket属性参数中的应用参数SO_REUSERADDR,实现地址的可重复利用
2)FD_SET(int fd, fd_set *fdset):向文件描述符集合中增加一个新的文件描述符
3)FD_CLR(int fd, fd_set *fdset):向文件描述符集合中删除一个文件描述符
【Socket】linux网络多路复用IO技术的更多相关文章
- Linux网络编程-IO复用技术
IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了.Linux中,提 ...
- linux网络编程 IO多路复用 select epoll
本文以我的小型聊天室为例,对于服务器端的代码,做了三次改进,我将分别介绍阻塞式IO,select,epoll . 一:阻塞式IO 对于聊天室这种程序,我们最容易想到的是在服务器端accept之后,然后 ...
- [转载] Linux下多路复用IO接口 epoll select poll 的区别
原地址:http://bbs.linuxpk.com/thread-43628-1-1.html 废话不多说,一下是本人学习nginx 的时候总结的一些资料,比较乱,但看完后细细揣摩一下应该就弄明白区 ...
- linux网络编程IO模型
同步与异步: 同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成. 异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要 ...
- Linux下多路复用IO接口epoll/select/poll的区别
select比epoll效率差的原因:select是轮询,epoll是触发式的,所以效率高. Select: 1.Socket数量限制:该模式可操作的Socket数由FD_SETSIZE决定,内核默认 ...
- LINUX网络编程 IO 复用
参考<linux高性能服务器编程> LINUX下处理多个连接时候,仅仅使用多线程和原始socket函数,效率十分低下 于是就出现了selelct poll epoll等IO复用函数. 这 ...
- Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)
Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...
- 转:Linux网络IO并行化技术概览
转:http://codinginet.com/articles/view/201605-linux_net_parallel?simple=1&from=timeline&isapp ...
- Socket网络编程-IO各种概念及多路复用
Socket网络编程-IO各种概念及多路复用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.操作系统相关知识 1>.同步和异步 函数或方法被调用的时候,调用者是否得到最 ...
随机推荐
- “医疗信息化行业之中的联发科”- 我们在医疗行业中的定位及目标 想做一个面对中小企业的专业上游软件供应商 台湾联发科技颠覆掉的是一个封闭的手机产业系统 解决方案,即AgileHIS.NET数字化医院基础方案
“医疗信息化行业之中的联发科”- 我们在医疗行业中的定位及目标 我们做中国医疗信息化行业之中的联发科 ---我们在医疗行业中的定位及目标 从我个人来讲,我从2001年到现在这10年之间基本上一直在 ...
- socket编程及API简介
什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域 ...
- Python学习笔记(四)——编码和字符串
一.编码 1.编码类别: (1)ASCII码:127个字母被编码到计算机里,也就是大小写英文字母.数字和一些符号 (2)GB2312码:中国制定的用于加入中文汉字的编码 (3)Unicode:防止由于 ...
- 【Android】详解Android的menu菜单
在软件应用过程中,菜单的存在是必不可少的,我这次讲一下,我对android菜单的一个基础做法吧 Android的菜单分为三种类型:选项菜单(Option Menu).上下文菜单(Context Men ...
- 安装Tomcat的Apr
转:http://www.cnblogs.com/littlehb/archive/2013/04/02/2994785.html 安装Tomcat的Apr,提升性能 发现 Tomcat 可以用 Ap ...
- Spark弹性分布式数据集RDD
RDD(Resilient Distributed Dataset)是Spark的最基本抽象,是对分布式内存的抽象使用,实现了以操作本地集合的方式来操作分布式数据集的抽象实现.RDD是Spark最核心 ...
- OpenCV 学习笔记03 findContours函数
opencv-python 4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...
- 如何检查后台服务(Android的Service类)是否正在运行?
private boolean isServiceRunning() { ActivityManager manager = (ActivityManager) getSystemService(AC ...
- MySQL-InnoDB Compact 行记录格式
InnoDB存储引擎提供了compact(5.1后的默认格式)和redundant两个格式来存放行记录数据.redundant格式是为了兼容之前的版本而保留. mysql> show table ...
- Python 文件 tell() 方法
描述 Python 文件 tell() 方法返回文件的当前位置,即文件指针当前位置. 语法 tell() 方法语法如下: fileObject.tell() 参数 无 返回值 返回文件的当前位置. 实 ...