socket编程的同步、异步与阻塞、非阻塞示例详解之一
来源:互联网 发布:mac怎么免费翻墙 编辑:程序博客网 时间:2024/06/06 20:23
简介
图 1. 基本 Linux I/O 模型的简单矩阵
每个 I/O 模型都有自己的使用模式,它们对于特定的应用程序都有自己的优点。
本节将简要对其一一进行介绍。
一、同步阻塞模式
在这个模式中,用户空间的应用程序执行一个系统调用,并阻塞,直到系统调用完成为止(数据传输完成或发生错误)。
/*
* \brief
* tcp client
*/
#define SERVPORT 8080
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd, recvbytes;
char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
char snd_buf[MAXDATASIZE];
struct hostent *host; /* struct hostent
* {
* char *h_name; // general hostname
* char **h_aliases; // hostname's alias
* int h_addrtype; // AF_INET
* int h_length;
* char **h_addr_list;
* };
*/
struct sockaddr_in server_addr;
if (argc < 3)
{
printf("Usage:%s [ip address] [any string]\n", argv[0]);
return 1;
}
*snd_buf = '\0';
strcat(snd_buf, argv[2]);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVPORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
memset(&(server_addr.sin_zero), 0, 8);
/* create the connection by socket
* means that connect "sockfd" to "server_addr"
* 同步阻塞模式
*/
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
/* 同步阻塞模式 */
if (send(sockfd, snd_buf, sizeof(snd_buf), 0) == -1)
{
perror("send:");
exit(1);
}
printf("send:%s\n", snd_buf);
/* 同步阻塞模式 */
if ((recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, 0)) == -1)
{
perror("recv:");
exit(1);
}
rcv_buf[recvbytes] = '\0';
printf("recv:%s\n", rcv_buf);
close(sockfd);
return 0;
}
显然,代码中的connect, send, recv都是同步阻塞工作模式,
在结果没有返回时,程序什么也不做,
二、同步非阻塞模式
同步阻塞 I/O 的一种效率稍低的变种是同步非阻塞 I/O。
在这种模型中,系统调用是以非阻塞的形式打开的。
这意味着 I/O 操作不会立即完成, 操作可能会返回一个错误代码,
说明这个命令不能立即满足(EAGAIN 或 EWOULDBLOCK),
非阻塞的实现是 I/O 命令可能并不会立即满足,需要应用程序调用许多次来等待操作完成。
这可能效率不高,
因为在很多情况下,当内核执行这个命令时,应用程序必须要进行忙碌等待,直到数据可用为止,
或者试图执行其他工作。
因为数据在内核中变为可用到用户调用 read 返回数据之间存在一定的间隔,这会导致整体数据吞吐量的降低。
/*
* \brief
* tcp client
*/
#define SERVPORT 8080
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd, recvbytes;
char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
char snd_buf[MAXDATASIZE];
struct hostent *host; /* struct hostent
* {
* char *h_name; // general hostname
* char **h_aliases; // hostname's alias
* int h_addrtype; // AF_INET
* int h_length;
* char **h_addr_list;
* };
*/
struct sockaddr_in server_addr;
int flags;
int addr_len;
if (argc < 3)
{
printf("Usage:%s [ip address] [any string]\n", argv[0]);
return 1;
}
*snd_buf = '\0';
strcat(snd_buf, argv[2]);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVPORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
memset(&(server_addr.sin_zero), 0, 8);
addr_len = sizeof(struct sockaddr_in);
/* Setting socket to nonblock */
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, flags|O_NONBLOCK);
/* create the connection by socket
* means that connect "sockfd" to "server_addr"
* 同步阻塞模式
*/
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
/* 同步非阻塞模式 */
while (send(sockfd, snd_buf, sizeof(snd_buf), MSG_DONTWAIT) == -1)
{
sleep(1);
printf("sleep\n");
}
printf("send:%s\n", snd_buf);
/* 同步非阻塞模式 */
while ((recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, MSG_DONTWAIT)) == -1)
{
sleep(1);
printf("sleep\n");
}
rcv_buf[recvbytes] = '\0';
printf("recv:%s\n", rcv_buf);
close(sockfd);
return 0;
}
异步阻塞模式,异步非阻塞模式以及server端程序见本文的第二部分。
http://blog.chinaunix.net/uid-26000296-id-3755268.html
图 1. 基本 Linux I/O 模型的简单矩阵
每个 I/O 模型都有自己的使用模式,它们对于特定的应用程序都有自己的优点。
本节将简要对其一一进行介绍。
一、同步阻塞模式
在这个模式中,用户空间的应用程序执行一个系统调用,并阻塞,直到系统调用完成为止(数据传输完成或发生错误)。
/*
* \brief
* tcp client
*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <string.h>
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd, recvbytes;
char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
char snd_buf[MAXDATASIZE];
struct hostent *host; /* struct hostent
* {
* char *h_name; // general hostname
* char **h_aliases; // hostname's alias
* int h_addrtype; // AF_INET
* int h_length;
* char **h_addr_list;
* };
*/
struct sockaddr_in server_addr;
if (argc < 3)
{
printf("Usage:%s [ip address] [any string]\n", argv[0]);
return 1;
}
*snd_buf = '\0';
strcat(snd_buf, argv[2]);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVPORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
memset(&(server_addr.sin_zero), 0, 8);
/* create the connection by socket
* means that connect "sockfd" to "server_addr"
* 同步阻塞模式
*/
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
/* 同步阻塞模式 */
if (send(sockfd, snd_buf, sizeof(snd_buf), 0) == -1)
{
perror("send:");
exit(1);
}
printf("send:%s\n", snd_buf);
/* 同步阻塞模式 */
if ((recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, 0)) == -1)
{
perror("recv:");
exit(1);
}
rcv_buf[recvbytes] = '\0';
printf("recv:%s\n", rcv_buf);
close(sockfd);
return 0;
}
显然,代码中的connect, send, recv都是同步阻塞工作模式,
在结果没有返回时,程序什么也不做,
二、同步非阻塞模式
同步阻塞 I/O 的一种效率稍低的变种是同步非阻塞 I/O。
在这种模型中,系统调用是以非阻塞的形式打开的。
这意味着 I/O 操作不会立即完成, 操作可能会返回一个错误代码,
说明这个命令不能立即满足(EAGAIN 或 EWOULDBLOCK),
非阻塞的实现是 I/O 命令可能并不会立即满足,需要应用程序调用许多次来等待操作完成。
这可能效率不高,
因为在很多情况下,当内核执行这个命令时,应用程序必须要进行忙碌等待,直到数据可用为止,
或者试图执行其他工作。
因为数据在内核中变为可用到用户调用 read 返回数据之间存在一定的间隔,这会导致整体数据吞吐量的降低。
/*
* \brief
* tcp client
*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <errno.h>
- #include <netdb.h>
- #include <string.h>
- #include <unistd.h>
- #include <fcntl.h>
#define SERVPORT 8080
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
int sockfd, recvbytes;
char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
char snd_buf[MAXDATASIZE];
struct hostent *host; /* struct hostent
* {
* char *h_name; // general hostname
* char **h_aliases; // hostname's alias
* int h_addrtype; // AF_INET
* int h_length;
* char **h_addr_list;
* };
*/
struct sockaddr_in server_addr;
int flags;
int addr_len;
if (argc < 3)
{
printf("Usage:%s [ip address] [any string]\n", argv[0]);
return 1;
}
*snd_buf = '\0';
strcat(snd_buf, argv[2]);
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket:");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVPORT);
inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
memset(&(server_addr.sin_zero), 0, 8);
addr_len = sizeof(struct sockaddr_in);
/* Setting socket to nonblock */
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, flags|O_NONBLOCK);
/* create the connection by socket
* means that connect "sockfd" to "server_addr"
* 同步阻塞模式
*/
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
/* 同步非阻塞模式 */
while (send(sockfd, snd_buf, sizeof(snd_buf), MSG_DONTWAIT) == -1)
{
sleep(1);
printf("sleep\n");
}
printf("send:%s\n", snd_buf);
/* 同步非阻塞模式 */
while ((recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, MSG_DONTWAIT)) == -1)
{
sleep(1);
printf("sleep\n");
}
rcv_buf[recvbytes] = '\0';
printf("recv:%s\n", rcv_buf);
close(sockfd);
return 0;
}
异步阻塞模式,异步非阻塞模式以及server端程序见本文的第二部分。
http://blog.chinaunix.net/uid-26000296-id-3755268.html
九三,君子终日乾乾,夕惕若,厉无咎。
【白话】九三,君子整天自强不息,晚上也不敢有丝毫的懈怠,这样即使遇到危险也会逢凶化吉。
《象》曰:“终日乾乾”,反复道也。
【白话】《象辞》说:“整天自强不息”,是因为要避免出现反复,不敢有丝毫大意。
0
上一篇:asterisk -r 出现Unable to connect to remote asterisk的解决方法
下一篇:socket编程的同步、异步与阻塞、非阻塞示例详解之二
相关热门文章
- c++ virtual析构函数详解...
- Linux设备驱动程序学习(5)-...
- Oracle:replace和translate函...
- 关于ORACLE COMMIT操作的详解...
- Linux逻辑卷详解总结
- socket中的短连接与长连接,心...
- Tomcat的性能与最大并发(1000)...
- Haproxy、Keepalived双主高可...
- Nginx深入详解之日志
- socket编程的同步、异步与阻塞...
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
0 0
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- Socket同步、异步与阻塞、非阻塞
- socket编程的几个概念.同步,异步,阻塞,非阻塞
- Linux内核编程风格
- vim常用的命令,供备忘
- 如何下载db2的安装包/补丁包/介质/Fix Pack?
- 什么是互联网金融
- asterisk -r 出现Unable to connect to remote asterisk的解决方法
- socket编程的同步、异步与阻塞、非阻塞示例详解之一
- socket编程的同步、异步与阻塞、非阻塞示例详解之二
- 别怕,手把手带你撕、拉、扯下SpringMVC的外衣
- socket简单应用服务端代码(原创)tcp c/s
- Linux文件权限
- 里氏七大原则
- Another MySQL daemon already running with the same unix socket
- SO_KEEPALIVE选项
- 查看程序线程数 文件打开数
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
曹子里绢花
绢花布置
古代绢花
杜绢花
绢花飞
绢花图片及价格
绢花是什么花
婚礼绢花布置
绣湖
绣塌
绣春刀1
绣红旗
304不绣钢
不绣钢
绣色可餐
十字绣怎么绣
绣生作品
绣春刀3
办公室绣感
绣眼鸟叫声
飞行的绣感
花下绣芙蓉
绣红旗简谱
名门绣娘
绣红旗原唱
绣春刀修罗战场
绣的拼音
绣组词
绣品街
绣娘
绣娘 宛海
在衣服上绣字简单针法图解
绣一字眉多少钱
衣服上绣字
不绣钢发光字
绣眉一字眉
毛巾绣字
丝带绣绣字怎么绣
十字绣的字怎么绣
+字绣
绣字组词