【Socket】linux网络多路复用IO技术
来源:互联网 发布:不明觉厉等网络流行语 编辑:程序博客网 时间:2024/06/04 20:28
1.mystery引入
1)Select是一种多路复用IO输入输出模式,在linux的输入输出编程中通过select的轮询机制,发现可用/可读或可写的接口。
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 200int 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技术】linux网络多路复用IO技术
- Linux网络编程 IO多路复用
- linux c/c++ 聊天小程序代码示例 (使用socket 和 IO 多路复用技术)
- linux c/c++ 聊天小程序代码示例 (使用socket 和 IO 多路复用技术)
- Linux IO多路复用之epoll网络编程
- linux网络编程 IO多路复用 select epoll
- IO多路复用技术
- [网络编程] IO多路复用
- linux下socket编程IO多路复用select模型
- linux socket的IO多路复用简单例子(一)
- linux socket的IO多路复用简单例子(二)
- linux socket的IO多路复用简单例子(三)
- linux socket的IO多路复用简单例子(四)
- Linux IO多路复用
- Linux IO多路复用
- Linux IO 多路复用详解
- Linux :IO多路复用模型
- Maven 与 MyEclipse10.6整合
- 实习笔记
- 继承DispatchAction可在一个Action里完成多个操作
- 应用数据升级
- USACO Section 1.3.1 Mixing Milk
- 【Socket】linux网络多路复用IO技术
- 存储入门:LUN概念
- linux下面 c++ string的编码
- 通用队列的实现
- Android数据库的操作
- MFC中设置静态文本的字体颜色、背景透明以及解决字体重叠
- Linux中JDK1.6的安装和配置方法
- 取出字符串的某一位用ASCII修改为其他字符
- (超强分析单人操作主机)程序中线性表存储数据