LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 4360|回复: 7

使用aio写socket通信程序

[复制链接]
发表于 2006-12-10 16:36:36 | 显示全部楼层 |阅读模式
以前我写了一篇用SIGIO完成socket编程的帖子。
http://linuxsir.cn/bbs/showthread.php?t=214611
这篇文章采用一种更好的方法来完成。
发送端代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <errno.h>
  6. #include <netinet/in.h>                 /*socket address struct*/
  7. #include <arpa/inet.h>                        /*host to network convertion*/
  8. #include <sys/socket.h>
  9. #include <signal.h>
  10. #define MAX_TRANSPORT_LENTH 512
  11. int main()
  12. {
  13.         struct sockaddr_in addr;
  14.         memset(&addr,0,sizeof(addr));
  15.         addr.sin_family =  AF_INET;
  16.         addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  17.         addr.sin_port = htons(50001);
  18.        
  19.         int sock;
  20.         sock = socket(AF_INET,SOCK_DGRAM,0);
  21.         if(sock == -1)
  22.         {
  23.                 perror("Create socket failed");
  24.                 exit(-1);
  25.         }
  26.        
  27.         int ret;
  28.         ret = connect(sock,(struct sockaddr *)&addr,sizeof(addr));
  29.         if(ret == -1)
  30.         {
  31.                 perror("Connect socket failed");
  32.                 exit(-1);               
  33.         }               
  34.         while(1)
  35.         {
  36.                 printf("Will send messge to server\n");
  37.                 write(sock,"Some unknown infomation\n",MAX_TRANSPORT_LENTH);
  38.                 sleep(1);
  39.         }
  40.        
  41. }
复制代码
发送端同上篇帖子相比,没啥区别。
主要不同的在于接收端,因为是采用了aio,所以很有些不同
接收端代码
  1. #include <aio.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <fcntl.h>
  6. #include <errno.h>
  7. #include <netinet/in.h>                 /*socket address struct*/
  8. #include <arpa/inet.h>                        /*host to network convertion*/
  9. #include <sys/socket.h>
  10. #include <sys/types.h>
  11. #include <signal.h>
  12. //#include <sys/ioctl.h>
  13. #define MAX_TRANSPORT_LENTH 512
  14. #define MAX_LIST                5
  15. void sig_handler(int signo, siginfo_t *info, void *context )
  16. {
  17.         int ret;
  18.         struct aiocb *req;
  19.         /* Ensure it's our signal */
  20.         if (info->si_signo == SIGIO) {
  21.                 req = (struct aiocb *)info->si_value.sival_ptr;
  22.                 if (aio_error( req ) == 0) {
  23.                         ret = aio_return( req );
  24.                         (char*)(req->aio_buf+ret) == '\0';//通常是拷贝一下数据,交给线程池去处理,以空间换取时间,从而加快主循环
  25.                         puts(req->aio_buf);
  26.                 }
  27.         }
  28.         return;       
  29. }
  30. int main()
  31. {
  32.         int skt_fd,ret;
  33.         struct aiocb my_aiocb;
  34.         struct sigaction sig_act;
  35.        
  36.         struct sockaddr_in addr;
  37.         memset(&addr,0,sizeof(addr));
  38.         addr.sin_family =  AF_INET;
  39.         addr.sin_addr.s_addr = INADDR_ANY;
  40.         addr.sin_port = htons(50001);
  41.        
  42.        
  43.         skt_fd = socket(AF_INET, SOCK_DGRAM, 0);
  44.         if(skt_fd == -1)
  45.         {
  46.                 perror("Create socket failed");
  47.                 exit(-1);
  48.         }
  49.         ret = bind(skt_fd,(struct sockaddr *)&addr,sizeof(addr));
  50.         if(-1 == ret)
  51.         {
  52.                 perror("Bind socket failed");
  53.                 exit(-1);
  54.         }
  55.         memset(&my_aiocb,0,sizeof(my_aiocb));
  56.         my_aiocb.aio_buf = malloc(MAX_TRANSPORT_LENTH+1);       
  57.         if (!my_aiocb.aio_buf)
  58.                 perror("malloc");
  59.        
  60.         my_aiocb.aio_fildes = skt_fd;
  61.         my_aiocb.aio_nbytes = MAX_TRANSPORT_LENTH;
  62.         my_aiocb.aio_offset = 0;
  63.        
  64.         my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  65.         my_aiocb.aio_sigevent.sigev_signo = SIGIO;
  66.         my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
  67.        
  68.         sigemptyset(&sig_act.sa_mask);
  69.         sig_act.sa_flags = SA_SIGINFO;
  70.         sig_act.sa_sigaction = sig_handler;       
  71.        
  72.         const struct aiocb *cblist[MAX_LIST] ={&my_aiocb,NULL,NULL,NULL,NULL};
  73.         sigaction( SIGIO, &sig_act, NULL );
  74.        
  75.         ret = aio_read( &my_aiocb );       
  76.         //程序挂起直到等到某个信号
  77.         while ( aio_suspend( cblist, MAX_LIST, NULL ) == 0)
  78.         {
  79.             ret = aio_read( &my_aiocb );
  80.         };
  81.         puts("Interrupted finish.");
  82.         close(skt_fd);       
  83. }
复制代码
在这里,如果用my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;
则可以指定一个回调函数来完成读取数据的操作,这种方法还是希望对此文感兴趣的伙伴加以完善吧。
发表于 2006-12-11 14:03:44 | 显示全部楼层
linux下据说还是epoll的效率更高吧
回复 支持 反对

使用道具 举报

发表于 2007-3-4 16:32:07 | 显示全部楼层
编译接受程序出错:

[aaron@localhost tcp]$ gcc -o aiorecv aiorecv.c
aiorecv.c: 在函数 ‘sig_handler’ 中:
aiorecv.c:27: 警告:传递实参 1(属于 ‘puts’)丢弃了指针目标类型的限定
aiorecv.c: 在函数 ‘main’ 中:
aiorecv.c:42: 警告:隐式声明与内建函数 ‘memset’ 不兼容
/tmp/ccIg4qNh.o: In function `sig_handler':aiorecv.c.text+0x20):对‘aio_error’未定义的引 用
:aiorecv.c.text+0x2f):对‘aio_return’未定义的引用
/tmp/ccIg4qNh.o: In function `main':aiorecv.c.text+0x21d):对‘aio_read’未定义的引用
:aiorecv.c.text+0x230):对‘aio_read’未定义的引用
:aiorecv.c.text+0x251):对‘aio_suspend’未定义的引用
collect2: ld 返回 1
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-3-5 11:13:22 | 显示全部楼层
编译时加上-lr选项
回复 支持 反对

使用道具 举报

发表于 2007-3-5 12:47:53 | 显示全部楼层
aio是啥东东?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-3-5 13:59:22 | 显示全部楼层
异步输入输出
回复 支持 反对

使用道具 举报

发表于 2009-11-4 00:43:12 | 显示全部楼层
写的真不错!
回复 支持 反对

使用道具 举报

发表于 2010-4-19 22:54:10 | 显示全部楼层
Post by realtang;1658105
编译时加上-lr选项


在Ubuntu 9.10下这个编译选项已经改为 -lrt 了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表