第16章 非阻塞式I/O
时间:2022-05-03
本文章向大家介绍第16章 非阻塞式I/O,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
执行时间:
停等版本(完全阻塞) 》 select加阻塞I/O版本 》 fork多进程版本(Linux下多线程也应该差不多) 》 非阻塞I/O版本
非阻塞读写
#include "../Gnet.h"
void do_client(int connfd)
{
char to[MAX_LINE], fr[MAX_LINE];
char *toiptr, *tooptr, *friptr, *froptr;
int val, stdineof, maxfd, n, nwritten;
fd_set rset, wset;
val = fcntl(connfd, F_GETFL, 0);
fcntl(connfd, F_SETFL, val|O_NONBLOCK);
val = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, val|O_NONBLOCK);
val = fcntl(STDOUT_FILENO, F_GETFL, 0);
fcntl(STDOUT_FILENO, F_SETFL, val|O_NONBLOCK);
toiptr = tooptr = to;
friptr = froptr = fr;
stdineof = 0;
maxfd = MAX(MAX(STDIN_FILENO, STDOUT_FILENO), connfd);
while(1)
{
FD_ZERO(&rset);
FD_ZERO(&wset);
if(stdineof==0 && toiptr<&to[MAX_LINE])//标准输入->套接字 还有数据要发送&&缓冲区还有容量
FD_SET(STDIN_FILENO, &rset);
if(friptr<&fr[MAX_LINE])//套接字->标准输出 缓冲区还有空闲
FD_SET(connfd, &rset);
if(tooptr!=toiptr)
FD_SET(connfd, &wset);
if(froptr!=friptr)
FD_SET(STDOUT_FILENO, &wset);
select(maxfd+1,&rset,&wset,NULL,NULL);
if(FD_ISSET(STDIN_FILENO, &rset))
{
if((n = read(STDIN_FILENO, toiptr, &to[MAX_LINE]-toiptr)) < 0)
{
if(errno != EWOULDBLOCK)
perr_exit("read error on stdin");
}
else if(n == 0)
{
fprintf(stderr,"EOF on stdinn");
stdineof = 1;
if(tooptr == toiptr)
shutdown(connfd, SHUT_WR);
}
else
{
fprintf(stderr, "read %d bytes from stdinn", n);
toiptr += n;
FD_SET(connfd, &wset);
}
}
if(FD_ISSET(connfd, &rset))
{
if((n = read(connfd, friptr, &fr[MAX_LINE]-friptr)) < 0)
{
if(errno != EWOULDBLOCK)
perr_exit("read error on socker");
}
else if(n == 0)
{
fprintf(stderr, "EOF on socketn");
if(stdineof)
return;
else
perr_exit("server terminated prematurely");
}
else
{
fprintf(stderr, "read %d bytes from socketn", n);
friptr += n;
FD_SET(STDOUT_FILENO, &wset);
}
}
if(FD_ISSET(STDOUT_FILENO, &wset) && ((n = friptr-froptr) > 0 ))
{
if((nwritten = write(STDOUT_FILENO, froptr, n)) < 0)
{
if(errno != EWOULDBLOCK)
perr_exit("write error to stdout");
}
else
{
fprintf(stderr, "wrote %d bytes to stdoutn", nwritten);
froptr += nwritten;
if(froptr == friptr)
froptr = friptr = fr;
}
}
if(FD_ISSET(connfd, &wset) && ((n = toiptr-tooptr) > 0))
{
if((nwritten = write(connfd, tooptr, n)) < 0)
{
if(errno != EWOULDBLOCK)
perr_exit("write error to socket");
}
else
{
fprintf(stderr, "wrote %d bytes to socketn", nwritten);
tooptr += nwritten;
if(tooptr == toiptr)
{
toiptr = tooptr = to;
if(stdineof)
shutdown(connfd, SHUT_WR);
}
}
}
}
}
int main(int argc, const char* argv[])
{
int connfd;
struct sockaddr_in server_addr;
if(argc < 2)
perr_exit("usage : client <IPaddress>");
connfd = Socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
Connect(connfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
do_client(connfd);
return 0;
}
多进程版本
#include "../Gnet.h"
void do_client(int connfd)
{
char buf[MAX_LINE];
pid_t pid;
if((pid = fork()) == 0)
{
while(Readline(connfd, buf, MAX_LINE) > 0)
fputs(buf, stdout);
kill(getppid(), SIGTERM);
exit(0);
}
else
{
while(fgets(buf, MAX_LINE, stdin) != NULL)
Write(connfd, buf, strlen(buf));
shutdown(connfd, SHUT_WR);
pause();
}
}
int main(int argc, const char* argv[])
{
int connfd;
struct sockaddr_in server_addr;
if(argc < 2)
perr_exit("usage : client <IPaddress>");
connfd = Socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
Connect(connfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
do_client(connfd);
return 0;
}
github:https://github.com/gongluck/unp-notes
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JavaScript 技术篇-js创建dom节点,并设置属性
- 容器中的数据管理
- Java基础 方法
- Python 技术篇-pyperclip库实现读取写入剪切板,超简单
- 基于consul的Docker-overlay跨多宿主机容器网络
- Python 微信机器人-向指定名称的好友发送微信消息
- JavaScript技术篇-js提升网页视频播放速率,提高慕课网视频播放速度
- 使用docker五步搭建ELK日志收集分析系统
- HDFS之SequenceFile和MapFile
- 配置ELK技术栈来分析apache tomcat日志
- LVS DR模式搭建,keepalived + lvs
- Ubuntu安装docker
- DockerFile简介与实例
- Elasticsearch2.3官方Dockerfile解析
- openstack架构解析