linux网络编程之异步通信机制
2018-01-18 17:13
232 查看
内核通过使用异步I/O,在某一进程需要处理的事件发生(例如,接收到新的连接请求)时,向该进程发送一个SIGIO信号。这样,应用进程不需要不停地等待着某些事件的发生,而可以往下运行,以完成其他的工作。只有收到从内核发来的SIGIO信号时,才去处理它(例如,读取数据)。
异步I/O:使用fcntl()函数实现高效率的异步I/O,首先必须试用fcntl的F_SETOWN命令,使套接字归属于当前进程,以内核能够判断应该向哪个进程发送信号。接下来,使用fcntl的F_SETFL命令将套接字的状态标志位设置成异步通知方式(使用O_ASYNC参数)。
实例
/*async_server.c*/
/*async_server.c*/
/*server.c*/
//使用fcntl()函数实现异步通信方式
//tcp网络协议编程
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#define PORT 4321
#define MAX_QUE_CONN_NM 5
#define BUFFER_SIZE 1024
int sin_size;
int client_fd; //接收到的套接字ID
int sockid; //套接字描述符
struct sockaddr_in server_sockaddr,client_sockaddr;
char buf[BUFFER_SIZE];
int recvbytes; //接收到的字节数
void do_work() /*模拟的任务,这里只是每秒去打印一句信息*/
{
while(1)
{
printf("i am working...\n");
sleep(1);
}
}
void accept_async() /*异步信号处理函数,处理新的套接字的连接和数据*/
{
sin_size=sizeof(client_sockaddr);
/*等待连接*/
if( (client_fd=accept(sockid,(struct sockaddr*)&client_sockaddr,&sin_size)) == -1 )
{
printf("accept error\n");
exit(1);
}
printf("the client_id is:%d\n",client_fd);
memset(buf,0,sizeof(buf));
if( (recvbytes= recv(client_fd,buf,BUFFER_SIZE,0) ) == -1 )
{
printf("recv error\n");
exit(1);
}
printf("receive data %d\n",strlen(buf));
printf("receive a message:%s\n",buf);
}
int main()
{
int i=1;
int flags;
sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid == -1)
{
//创建套接字失败
printf("socket error\n");
exit(1);
}
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(PORT); //端口号
server_sockaddr.sin_addr.s_addr=INADDR_ANY; //IP地址 //IP地址可以指定,或者使用宏INADDR_ANY
//表示运行套接字与服务器的任一网络接口进行绑定
bzero(&(server_sockaddr.sin_zero),8);
setsockopt(sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));
//绑定地址
if( bind(sockid,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr)) == -1 )
{
printf("bind error\n");
exit(1);
}
printf("bind success\n");
/*调用listen()函数,创建为处理请求的队列*/
if( listen(sockid,MAX_QUE_CONN_NM) == -1 )
{
printf("listen error\n");
exit(1);
}
printf("listen...\n");
/*设置异步方式*/
/*SIGIO信号处理函数的注册*/ //使用signal()函数
signal(SIGIO,accept_async);
/*使套接字归属于该进程*/
fcntl(sockid,F_SETOWN,getpid());
/*获得套接字的状态标志位*/
flags=fcntl(sockid,F_GETFL);
if(flags<0 || fcntl(sockid,F_SETFL,flags|O_ASYNC) <0)
{
/*设置成异步访问模式*/
printf("fcntl error\n");
}
do_work();
//结束连接
close(sockid);
exit(0);
}/*client.c*/
![](https://img-blog.csdn.net/20180118171252793?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjczMTI5NDM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
异步I/O:使用fcntl()函数实现高效率的异步I/O,首先必须试用fcntl的F_SETOWN命令,使套接字归属于当前进程,以内核能够判断应该向哪个进程发送信号。接下来,使用fcntl的F_SETFL命令将套接字的状态标志位设置成异步通知方式(使用O_ASYNC参数)。
实例
/*async_server.c*/
/*async_server.c*/
/*server.c*/
//使用fcntl()函数实现异步通信方式
//tcp网络协议编程
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#define PORT 4321
#define MAX_QUE_CONN_NM 5
#define BUFFER_SIZE 1024
int sin_size;
int client_fd; //接收到的套接字ID
int sockid; //套接字描述符
struct sockaddr_in server_sockaddr,client_sockaddr;
char buf[BUFFER_SIZE];
int recvbytes; //接收到的字节数
void do_work() /*模拟的任务,这里只是每秒去打印一句信息*/
{
while(1)
{
printf("i am working...\n");
sleep(1);
}
}
void accept_async() /*异步信号处理函数,处理新的套接字的连接和数据*/
{
sin_size=sizeof(client_sockaddr);
/*等待连接*/
if( (client_fd=accept(sockid,(struct sockaddr*)&client_sockaddr,&sin_size)) == -1 )
{
printf("accept error\n");
exit(1);
}
printf("the client_id is:%d\n",client_fd);
memset(buf,0,sizeof(buf));
if( (recvbytes= recv(client_fd,buf,BUFFER_SIZE,0) ) == -1 )
{
printf("recv error\n");
exit(1);
}
printf("receive data %d\n",strlen(buf));
printf("receive a message:%s\n",buf);
}
int main()
{
int i=1;
int flags;
sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid == -1)
{
//创建套接字失败
printf("socket error\n");
exit(1);
}
server_sockaddr.sin_family=AF_INET;
server_sockaddr.sin_port=htons(PORT); //端口号
server_sockaddr.sin_addr.s_addr=INADDR_ANY; //IP地址 //IP地址可以指定,或者使用宏INADDR_ANY
//表示运行套接字与服务器的任一网络接口进行绑定
bzero(&(server_sockaddr.sin_zero),8);
setsockopt(sockid,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i));
//绑定地址
if( bind(sockid,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr)) == -1 )
{
printf("bind error\n");
exit(1);
}
printf("bind success\n");
/*调用listen()函数,创建为处理请求的队列*/
if( listen(sockid,MAX_QUE_CONN_NM) == -1 )
{
printf("listen error\n");
exit(1);
}
printf("listen...\n");
/*设置异步方式*/
/*SIGIO信号处理函数的注册*/ //使用signal()函数
signal(SIGIO,accept_async);
/*使套接字归属于该进程*/
fcntl(sockid,F_SETOWN,getpid());
/*获得套接字的状态标志位*/
flags=fcntl(sockid,F_GETFL);
if(flags<0 || fcntl(sockid,F_SETFL,flags|O_ASYNC) <0)
{
/*设置成异步访问模式*/
printf("fcntl error\n");
}
do_work();
//结束连接
close(sockid);
exit(0);
}/*client.c*/
/*client.c*/ #include <stdio.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <netdb.h> #define PORT 4321 #define BUFFER_SIZE 1024 int main(int argc,char *argv[]) { struct hostent *host; int sockid; //套接字描述符 int sendbyts; //实际发送的字节数 char buf[BUFFER_SIZE]; struct sockaddr_in serv_addr; if(argc<3) { fprintf(stderr,"USAGE:./client Hostname(or ip address) Text\n"); exit(1); } /*地址解析函数*/ /*************************** 函数原型:struct hostent *gethostbyname(const char *hostname); 函数参数:hostname 主机名 函数返回值:成功 指向hostent的指针 失败 -1 *****************************/ if( (host=gethostbyname(argv[1])) == NULL ) { printf("gethostbyname error\n"); exit(1); } memset(buf,0,sizeof(buf)); sprintf(buf,"%s",argv[2]); //创建socket sockid=socket(AF_INET,SOCK_STREAM,0); if(sockid == -1) { //创建套接字失败 printf("socket error\n"); exit(1); } /*设置socket_in中的相关参数*/ serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(PORT); //端口号 serv_addr.sin_addr=*((struct in_addr *)host->h_addr); //IP地址 //IP地址可以指定,或者使用宏INADDR_ANY //表示运行套接字与服务器的任一网络接口进行绑定 bzero(&(serv_addr.sin_zero),8); //连接服务器 /*调用connect()函数主动发起对服务器端的连接*/ /************************ 函数原型: int connect(int sockfd, const struct sockaddr * addr, socklen_t *addrlen) 函数参数: sockfd 套接字描述符 addr 客户端地址 addrlen 地址长度 函数返回值: 成功 接收到的非负套接字 失败 -1 ***********************/ if( connect(sockid,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr)) == -1 ) { printf("connect error\n"); exit(1); } /*发送消息给服务端*/ /***************** 函数原型:int send(int sockfd,const void *msg,int len,int flags) 函数参数:sockfd 套接字描述符 msg 指向要发送数据的指针 len 数据长度 flags 一般为0 函数返回值:成功 实际发送的字节数 失败 -1 ******************/ if( (sendbyts=send(sockid,buf,sizeof(buf),0)) == -1 ) { printf("send error\n"); exit(1); } close(sockid); return 0; }运行结果
相关文章推荐
- Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)
- Net线程间通信的异步机制
- .Net的异步机制(线程间通信) - step 5
- Net线程间通信的异步机制
- Android线程间异步通信机制源码分析
- .Net线程间通信的异步机制
- 进程间互斥、进程间同步 & 消息通信机制的同步、异步
- 什么是.Net的异步机制(线程间通信) - step 5
- 什么是.Net的异步机制(线程间通信) - step 5
- Net线程间通信的异步机制
- 具有安全机制的异步网络通信模块的设计
- Android 异步通信原理机制-- handler
- linux内核中异步通信机制--信号处理机制
- linux内核中异步通信机制--信号处理机制
- .Net线程间通信的异步机制(转)
- Apache Mina 入门 (二)—— 异步通信机制
- .Net的异步机制(线程间通信) - step 5
- Android 异步通信原理机制-- handler
- Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue
- Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)