高性能网络编程 - select系统调用
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h> //basename
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <assert.h>
#include <errno.h> int main(int argc, char *argv[]){
int i, maxi;
char buf[1024];
fd_set read_fds, all_read_fds;
fd_set exception_fds, all_exception_fds;
int nready, connectfd[FD_SETSIZE];
int connfd,sockfd,maxfd; struct sockaddr_in client_address;
socklen_t client_addrlen = sizeof(client_address); if(argc <= 2){
printf("usage: %s ip_address port_number\n", basename(argv[0]));
return 1;
} const char *ip = argv[1];
int port = atoi(argv[2]); int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port); int listenfd = socket(AF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);
ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
assert(ret != -1);
ret = listen(listenfd, 5);
assert(ret != -1); maxfd = listenfd;
maxi = -1;
for(i= 0; i < FD_SETSIZE; i++)
connectfd[i] = -1;
FD_ZERO(&all_read_fds);
FD_ZERO(&all_exception_fds);
FD_SET(listenfd, &all_read_fds);
//do not care about the OOB of listen socket while(1){
read_fds = all_read_fds;
exception_fds = all_exception_fds;
memset(buf, 0, sizeof(buf));
nready = select(maxfd + 1, &read_fds, NULL, &exception_fds, NULL);
//new client connection coming
if(FD_ISSET(listenfd, &read_fds)){
connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addrlen);
if(connfd < 0){
perror("accept failed\n");
exit(-1);
} for(i=0; i < FD_SETSIZE; i++)
if(connectfd[i] < 0){
connectfd[i] = connfd;
break;
}
if( i == FD_SETSIZE){
printf("too many clients..\n");
exit(-1);
}
// add new descriptor to the read set and exception set
FD_SET(connfd, &all_read_fds);
FD_SET(connfd, &all_exception_fds);
if(connfd > maxfd)
maxfd = connfd;
if(i > maxi)
maxi = i;// update the max index in connectfd[]
//we complete the listen socktet processing
if(--nready <= 0)
continue;
}
for(i = 0; i <= maxi; i++){
//check all the connected clients for data
if((sockfd = connectfd[i]) < 0)
continue;
if(FD_ISSET(sockfd, &read_fds)){
ret = recv(sockfd, buf, sizeof(buf) - 1, 0);
if(ret <= 0)
break;//connection closed
// process logic
printf("get %d bytes of normal data:%s\n", ret, buf);
//we complete the listen socktet processing
if(--nready <= 0)
continue;
}
for(i = 0; i <= maxi; i++){
//check all the connected clients for data
if((sockfd = connectfd[i]) < 0)
continue;
if(FD_ISSET(sockfd, &read_fds)){
ret = recv(sockfd, buf, sizeof(buf) - 1, 0);
if(ret <= 0)
break;//connection closed
// process logic
printf("get %d bytes of normal data:%s\n", ret, buf);
}else if(FD_ISSET(sockfd, &exception_fds)){
//handle exceptions
//get out of band data
ret = recv(connfd, buf, sizeof(buf) - 1, MSG_OOB);
if(ret <= 0)
break;
printf("get %d bytes of OOB data: %s", ret, buf); }
FD_CLR(sockfd, &all_read_fds);
FD_CLR(sockfd, &all_exception_fds);
//after we deal with this client
close(sockfd);
if(--nready <= 0)
break;
}
} close(listenfd);
return 0;
}
參考:《高性能server编程》和《UNP》
高性能网络编程 - select系统调用的更多相关文章
- 一文读懂高性能网络编程中的I/O模型
1.前言 随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力.本文(和下篇<高性能网络编程(六):一文读懂高性能网络编程中的线程模型>)旨在为大家提供有用的 ...
- 【原创】高性能网络编程(二):上一个10年,著名的C10K并发连接问题
1.前言 对于高性能即时通讯技术(或者说互联网编程)比较关注的开发者,对C10K问题(即单机1万个并发连接问题)应该都有所了解."C10K"概念最早由Dan Kegel发布于其个人 ...
- 【网络】高性能网络编程--下一个10年,是时候考虑C10M并发问题了
转载:http://www.52im.net/thread-568-1-1.html 1.前言 在本系列文章的上篇中我们回顾了过云的10年里,高性能网络编程领域著名的C10K问题及其成功的解决方案(上 ...
- 网络编程select函数
select函数的作用: 在编程的过程中,经常会遇到许多阻塞的函数,好像read和网络编程时使用的recv, recvfrom函数都是阻塞的函数,当函数不能成功执行的时候,程序就会一直阻塞在这里,无法 ...
- 高性能网络编程(一)----accept建立连接
编写服务器时,许多程序员习惯于使用高层次的组件.中间件(例如OO(面向对象)层层封装过的开源组件),相比于服务器的运行效率而言,他们更关注程序开发的效率,追求更快的完成项目功能点.希望应用代码完全不关 ...
- Linux之select系统调用_2
在上一篇博文中,我们的程序中我们有3个客户端,因此也事先建立了3个管道,每个客户端分别使用一个管道向服务器发送消息.而在服务器端使用select系统调用,只要监测到某一管道有消息写入,服务器就将其re ...
- Linux之select系统调用_1
SYNOPSIS /* According to POSIX.1-2001 */ #include <sys/select.h> /* According to earlier stand ...
- winsock编程select模型
winsock编程select模型 网络服务端连接数量过多时,为每一个连接申请一个线程会让机器性能急剧下降(大多说是因为线程在用户态和内核态之间切换会占用大量的CPU时间片).为了解决多线程带来的性能 ...
- 高性能网络编程(1)—accept建立连接(转载,作者:陶辉)
编 写服务器时,许多程序员习惯于使用高层次的组件.中间件(例如OO(面向对象)层层封装过的开源组件),相比于服务器的运行效率而言,他们更关注程序开发 的效率,追求更快的完成项目功能点.希望应用代码完全 ...
随机推荐
- ICA(独立成分分析)笔记
ICA又称盲源分离(Blind source separation, BSS) 它假设观察到的随机信号x服从模型,其中s为未知源信号,其分量相互独立,A为一未知混合矩阵. ICA的目的是通过且仅通过观 ...
- Matlab 从入门到精通 Chapter11 文件读取I/O
11.1 工作空间数据读取 将工作空间的变量保存为文件,可以使用save命令. save('filename') 将文件保存在当前目录下,文件名为filename.mat save('filenam ...
- vue 事件参数传$event打印当前组件
<template> <div class="hello"> <button v-on:click.once="getinfo($event ...
- css兼容性问题总结
DIV+CSS设计IE6.IE7.FF 兼容性 DIV+CSS网页布局这是一种趋势,我也开始顺应这股趋势了,不过在使用DIV+CSS网站设计的时候,应该注意css样式兼容不同浏览器问题,特别是对完全使 ...
- 模块 –OS & OS.PATH
模块-Os模块: os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 In [25]: os.getcwd() Out[25]: 'C:\\Users\\***' os.c ...
- [codevs3657]括号序列
题目大意:有一列只有'(',')','[',']'构成的括号序列,求在序列中至少加上多少括号,能使该序列合法. 解题思路:区间dp. 我们以$f[i][j]$表示把区间$[i,j]$添成合法括号所需的 ...
- 紫书 习题8-18 UVa 11536 (扫描法)
这道题貌似可以用滑动窗口或者单调栈做, 但是我都没有用到. 这道题要求连续子序列中和乘上最小值最大, 那么我们就可以求出每一个元素, 以它为最小值的的最大区间的值, 然后取max就ok了.那么怎么求呢 ...
- 总结使人进步,可视化界面GUI应用开发总结:Android、iOS、Web、Swing、Windows开发等
可视化界面的软件,是21世纪最主流的应用类型了,黑屏控制台的不适合普通用户. 2004年左右的时候,作为普通网民,接触的自然是可视化,准确是Windows那一套. 那个时候,Microsoft ...
- mysql5.7 安装方法 (跟旧的不一样了)
MySQL 5.7发布之后很多网友都在说,打开想安装文件夹.但是文件夹中没有DATA目录, 没有mysqly默认库.启动不了数据库,那是因为5.7的数据库的初始化方法和之前的初始化不一样了. 首先这里 ...
- 改动Android设备信息,如改动手机型号为iPhone7黄金土豪版!
首先你的手机必需要有ROOT权限,误操作有风险需慎重 请先开启手机的USB调试,防止手机改动后无法启动时导致的无法修复 1.假设你是在手机上改动,直接使用RE文件管理器,编辑/system/build ...