非阻塞式I/O包括非阻塞输入操作,非阻塞输出操作,非阻塞接收外来连接,非阻塞发起外出连接。包括的函数有:read, readv, recv, recvfrom, recvmsg, write, writev, send, sendto, sendmsg, accept。

将socket 设置为非阻塞模式有三种方法:

(1)创建socket的时候,指定socket是异步的,在type的参数中设置SOCK_NONBLOCK标志即可。

[objc] view plain copy

  1. int socket(int domain, int type, int protocol);
  2. int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);

(2)使用fcntl函数:[objc] view plain copy

  1. fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);

(3)使用ioctl函数:[objc] view plain copy

  1. ioctl(sockfd, FIONBIO, 1);  //1:非阻塞 0:阻塞

下面改写linux网络编程:使用多进程实现socket同时收发数据 中的程序[objc] view plain copy

  1. /*=============================================================================
  2. #     FileName: nonblocktcp.c
  3. #         Desc: set the connetfd unblock
  4. #       Author: licaibiao
  5. #   LastChange: 2017-02-14
  6. =============================================================================*/
  7. #include<stdio.h>
  8. #include<sys/types.h>
  9. #include<sys/socket.h>
  10. #include<unistd.h>
  11. #include<stdlib.h>
  12. #include<errno.h>
  13. #include<arpa/inet.h>
  14. #include<netinet/in.h>
  15. #include<string.h>
  16. #include<signal.h>
  17. #include <fcntl.h>
  18. #define MAXLINE 256
  19. #define PORT    6666
  20. void process_out(int signo)
  21. {
  22. exit(EXIT_SUCCESS);
  23. }
  24. void write_func(int pid, int fd)
  25. {
  26. char* write = "I am server";
  27. printf("write id = %d\n",pid);
  28. signal(SIGUSR1,process_out);
  29. while(1)
  30. {
  31. sleep(1);
  32. send(fd,write,strlen(write)+1,0);
  33. }
  34. }
  35. void read_func(int pid, int fd)
  36. {
  37. char readbuff[MAXLINE];
  38. int n = 0;
  39. printf("read id = %d \n",pid);
  40. memset(&readbuff,0,sizeof(readbuff));
  41. while(1)
  42. {
  43. n = recv(fd, readbuff, MAXLINE, 0);
  44. if(n > 0)
  45. {
  46. printf("server recv data: %s \n",readbuff);
  47. }
  48. else if(n == 0)
  49. {
  50. break;
  51. }
  52. sleep(1);
  53. //printf("===\n");
  54. };
  55. printf("exit read function\n");
  56. kill(pid, SIGUSR1);
  57. exit(EXIT_SUCCESS);
  58. }
  59. int main(void)
  60. {
  61. int listenfd,connetfd;
  62. int on = 1;
  63. int addrlen = 0;
  64. int flags;
  65. pid_t pid, pid_child, pid_send;
  66. struct sockaddr_in server_addr;
  67. struct sockaddr_in client_addr;
  68. if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  69. {
  70. printf("create socket err \n");
  71. }
  72. addrlen = sizeof(struct sockaddr_in);
  73. memset(&server_addr, 0, addrlen);
  74. server_addr.sin_family = AF_INET;
  75. server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  76. server_addr.sin_port = htons(PORT);
  77. if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
  78. {
  79. printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
  80. exit(0);
  81. }
  82. if( bind(listenfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
  83. {
  84. printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
  85. exit(0);
  86. }
  87. if( listen(listenfd, 10) == -1)
  88. {
  89. printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
  90. exit(0);
  91. }
  92. printf("wait client accpt \n");
  93. while(1)
  94. {
  95. if( (connetfd = accept(listenfd, (struct sockaddr*)&client_addr, &addrlen)) == -1)
  96. {
  97. printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
  98. continue;
  99. }
  100. /* set NONBLOCK */
  101. flags = fcntl(connetfd, F_GETFL, 0);
  102. fcntl(connetfd, F_SETFL, flags | O_NONBLOCK);
  103. signal(SIGCHLD, SIG_IGN);
  104. pid = fork();
  105. if(pid == -1)
  106. {
  107. printf("fork err \n");
  108. }
  109. if(pid == 0)
  110. {
  111. pid_child = fork();
  112. if(pid_child == 0)
  113. {
  114. pid_send = getpid();
  115. read_func(pid_send, connetfd);
  116. }
  117. else
  118. {
  119. pid_send = getpid();
  120. write_func(pid_send,connetfd);
  121. }
  122. }
  123. }
  124. }

在该程序中,当接收到客户端的一个连接后,将连接描述符设置成非阻塞的:[objc] view plain copy

  1. flags = fcntl(connetfd, F_GETFL, 0);
  2. fcntl(connetfd, F_SETFL, flags | O_NONBLOCK);

这样设置之后,在读和写函数中的send和recv函数都变为了非阻塞模式。在这里我们使用的是sleep来做一个延时循环检测数据可读和数据可发送。在这里常用的套接字超时并不是sleep函数。我们可以使用下面的三种套接字超时方法。

套接字超时:

(1)调用alarm,它在指定超时期满时产生SIGALARM信号,这与Linux信号处理类似。

[objc] view plain copy

  1. static void sig_alrm(int signo)
  2. {
  3. return;         /* just interrupt the recvfrom() */
  4. }
  5. void dg_cli(FILEFILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
  6. {
  7. int n;
  8. char    sendline[MAXLINE], recvline[MAXLINE + 1];
  9. signal(SIGALRM, sig_alrm);
  10. while (Fgets(sendline, MAXLINE, fp) != NULL) {
  11. sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
  12. alarm(5);
  13. if ( (n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) < 0) {
  14. if (errno == EINTR)
  15. fprintf(stderr, "socket timeout\n");
  16. else
  17. err_sys("recvfrom error");
  18. } else {
  19. alarm(0);
  20. recvline[n] = 0;    /* null terminate */
  21. fputs(recvline, stdout);
  22. }
  23. }
  24. }

(2)在select 中阻塞等待I/O(select 有内置的时间限制),以此代替直接阻塞在read或write调用上。

[objc] view plain copy

  1. int readable_select(int fd, int sec)
  2. {
  3. fd_set          rset;
  4. struct timeval  tv;
  5. FD_ZERO(&rset);
  6. FD_SET(fd, &rset);
  7. tv.tv_sec = sec;
  8. tv.tv_usec = 0;
  9. return(select(fd+1, &rset, NULL, NULL, &tv));
  10. /* 4> 0 if descriptor is readable */
  11. }

(3)使用较新的SO_RCVTIMEO和SO_SNDTIMEO套接字选项。

[objc] view plain copy

  1. void dg_cli(FILEFILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
  2. {
  3. int             n;
  4. char            sendline[MAXLINE], recvline[MAXLINE + 1];
  5. struct timeval  tv;
  6. tv.tv_sec = 5;
  7. tv.tv_usec = 0;
  8. setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  9. while (fgets(sendline, MAXLINE, fp) != NULL) {
  10. sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
  11. n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
  12. if (n < 0) {
  13. if (errno == EWOULDBLOCK) {
  14. fprintf(stderr, "socket timeout\n");
  15. continue;
  16. } else
  17. err_sys("recvfrom error");
  18. }
  19. recvline[n] = 0;    /* null terminate */
  20. fputs(recvline, stdout);
  21. }
  22. }

装载:http://blog.csdn.net/li_wen01/article/details/55098317

设置非阻塞socket收发数据相关推荐

  1. iphone开发之轻松搞定原生socket 编程,阻塞与非阻塞,收发自如

    iphone socket 开发 在iphone的平台下,要进行socket开发其实有很多种的方法,开源的库Asyncsocket,官方的CFSocket,还有BSD的socket. 这里要做一个简单 ...

  2. 使用select+非阻塞socket写的网络数据转发程序 « Xiaoxia[PG]

    使用select+非阻塞socket写的网络数据转发程序 « Xiaoxia[PG] 使用select+非阻塞socket写的网络数据转发程序 « Xiaoxia[PG] 从实践之中,我又学到东西了! ...

  3. linux下网络编程设置非阻塞,UNIX网络编程 非阻塞connect的实现

    一.<UNIX网络编程>-非阻塞connect 在一个TCP套接口被设置为非阻塞之后调用connect,connect会立即返回EINPROGRESS错误,表示连接操作正在进行中,但是仍未 ...

  4. socket编程 —— 非阻塞socket (转)---例子已上传至文件中

    在上一篇文章 <socket编程--一个简单的例子> http://blog.csdn.net/wind19/archive/2011/01/21/6156339.aspx 中写了一个简单 ...

  5. 使用NIO实现异步非阻塞Socket tcp通信

    使用NIO实现异步非阻塞Socket tcp通信 一.BIO与NIO IO(BIO)和NIO区别:其本质就是阻塞和非阻塞的区别 阻塞概念:应用程序在获取网络数据的时候,如果网络传输数据很慢,就会一直等 ...

  6. linux socket 阻塞服务端 非阻塞客户端,linux下异步RPC的阶段性总结-非阻塞SOCKET客户端...

    尽可能使用非阻塞socket int flags, s; flags = fcntl (fd, F_GETFL, 0); if (flags == -1){ close(fd); return -1; ...

  7. 深入理解阻塞socket和非阻塞socket

    什么是阻塞socket,什么是非阻塞socket.对于这个问题,我们要先弄清什么是阻塞/非阻塞.阻塞与非阻塞是对一个文件描述符指定的文件或设备的两种工作方式. 阻塞的意思是指,当试图对该文件描述符进行 ...

  8. linux 非阻塞 socket - Google 搜索

    linux 非阻塞 socket - Google 搜索 linux c实现超时.非阻塞socket的函数select - Yunlu Liu (刘云璐) sites.google.com/site/ ...

  9. python select實現非阻塞socket

    python select實現非阻塞socket - liukeforever的专栏 - 博客频道 - CSDN.NET python select實現非阻塞socket 分类: Python 201 ...

最新文章

  1. python代码怎么运行-python代码是怎样运行的
  2. TCP-IP详解:快速重传与快速恢复
  3. 管理员请注意 一条后门病毒攻击链正在针对服务器发起入侵
  4. Unity教程:如何使用枚举来帮助简化游戏开发
  5. Coolite 中GridView行按钮取行ID并调用服务器端代码
  6. mysql round 0.1111_听说Mysql你很豪横?-------------分分钟带你玩转SQL高级查询语句(库函数,存储过程)...
  7. 金山毒霸专业版高调上线 宣称杀毒速度增3倍
  8. carsim中质心加速度_Carsim整车建模参数.doc
  9. 2021年中国低地球轨道卫星(LEO)发射服务市场趋势报告、技术动态创新及2027年市场预测
  10. python时间模块倒计时_Python时间模块
  11. mysqldump+系统计划任务定时备份MySql数据
  12. eclipse 项目显示红叉
  13. Atitit 常见信息化系统类别erp mes crm cms oa 目录 1.  企业资源规划(ERP)、客户关系管理(CRM)、协同管理系统(CMS)是企业信息化的三大代表之作 1 2. 概
  14. Kaggle竞赛实战系列(一):手写数字识别器(Digit Recognizer)得分99.53%、99.91%和100%
  15. BorisFX Sapphire 2019 for AE Mac(蓝宝石插件) v2019.0.2激活版
  16. word压缩软件,免费
  17. 黑盒测试方法(五)正交实验设计方法
  18. 据说百度的月饼最差劲!!
  19. sigmoid和softmax
  20. python自动更换电脑桌面壁纸

热门文章

  1. Python对Excel文件多表对多表之间的匹配(两种不同表头)——之json版
  2. PHP Warning: ‘ vcruntime140.dll‘ 14.0 is not compatible with this PHP build linked with 14.16 in Unk
  3. 单片机_MFRC522射频模块使用方法(含代码)
  4. 关于pos打印机通过tcp/ip操作打印指令集
  5. 有源rc电压放大器实验报告_我们一起来认识一下RC反馈回路
  6. linux中如何知道了主机IP,获得主机名
  7. vscode 无法输入输出
  8. BI技巧丨近两年及当年月份数据汇总
  9. 【Python】输入一个整数,输出这个整数的所有数字和,例如输入256,则输出13
  10. Android网络功能开发(5)——Socket编程接口