Chinaunix首页 | 论坛 | 博客
  • 博客访问: 18001
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 57
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-20 09:56
文章分类

全部博文(9)

文章存档

2014年(9)

我的朋友

分类: LINUX

2014-02-27 16:04:42

简介
图 1. 基本 Linux I/O 模型的简单矩阵
基本 Linux I/O 模型的简单矩阵 
每个 I/O 模型都有自己的使用模式,它们对于特定的应用程序都有自己的优点。
本节将简要对其一一进行介绍。

一、同步阻塞模式
在这个模式中,用户空间的应用程序执行一个系统调用,并阻塞,直到系统调用完成为止(数据传输完成或发生错误)。

点击(此处)折叠或打开

  1. /*
  2.  * \brief
  3.  * tcp client
  4.  */

  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <sys/socket.h>
  8. #include <netdb.h>
  9. #include <string.h>
  10. #define SERVPORT 8080
  11. #define MAXDATASIZE 100

  12. int main(int argc, char *argv[])
  13. {
  14.   int sockfd, recvbytes;
  15.   char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
  16.   char snd_buf[MAXDATASIZE];
  17.   struct hostent *host; /* struct hostent
  18.                                      * {
  19.                                      * char *h_name; // general hostname
  20.                                      * char **h_aliases; // hostname's alias
  21.                                      * int h_addrtype; // AF_INET
  22.                                      * int h_length;
  23.                                      * char **h_addr_list;
  24.                                      * };
  25.                                      */
  26.   struct sockaddr_in server_addr;

  27.   if (argc < 3)
  28.   {
  29.     printf("Usage:%s [ip address] [any string]\n", argv[0]);
  30.     return 1;
  31.   }

  32.   *snd_buf = '\0';
  33.   strcat(snd_buf, argv[2]);

  34.   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  35.   {
  36.     perror("socket:");
  37.     exit(1);
  38.   }

  39.   server_addr.sin_family = AF_INET;
  40.   server_addr.sin_port = htons(SERVPORT);
  41.   inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
  42.   memset(&(server_addr.sin_zero), 0, 8);

  43.   /* create the connection by socket
  44.    * means that connect "sockfd" to "server_addr"
  45.    * 同步阻塞模式
  46.    */
  47.   if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
  48.   {
  49.     perror("connect");
  50.     exit(1);
  51.   }

  52.   /* 同步阻塞模式 */
  53.   if (send(sockfd, snd_buf, sizeof(snd_buf), 0) == -1)
  54.   {
  55.     perror("send:");
  56.     exit(1);
  57.   }
  58.   printf("send:%s\n", snd_buf);

  59.    /* 同步阻塞模式 */
  60.   if ((recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, 0)) == -1)
  61.   {
  62.     perror("recv:");
  63.     exit(1);
  64.   }

  65.   rcv_buf[recvbytes] = '\0';
  66.   printf("recv:%s\n", rcv_buf);

  67.   close(sockfd);
  68.   return 0;
  69. }
 显然,代码中的connect, send, recv都是同步阻塞工作模式,
在结果没有返回时,程序什么也不做,

二、同步非阻塞模式
同步阻塞 I/O 的一种效率稍低的变种是同步非阻塞 I/O。
在这种模型中,系统调用是以非阻塞的形式打开的。
这意味着 I/O 操作不会立即完成, 操作可能会返回一个错误代码,
说明这个命令不能立即满足(EAGAIN 或 EWOULDBLOCK),
非阻塞的实现是 I/O 命令可能并不会立即满足,需要应用程序调用许多次来等待操作完成。
这可能效率不高,
因为在很多情况下,当内核执行这个命令时,应用程序必须要进行忙碌等待,直到数据可用为止,
或者试图执行其他工作。
因为数据在内核中变为可用到用户调用 read 返回数据之间存在一定的间隔,这会导致整体数据吞吐量的降低。

点击(此处)折叠或打开

  1. /*
  2.  * \brief
  3.  * tcp client
  4.  */

  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <sys/socket.h>
  8. #include <sys/types.h>
  9. #include <errno.h>
  10. #include <netdb.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <fcntl.h>

  14. #define SERVPORT 8080
  15. #define MAXDATASIZE 100


  16. int main(int argc, char *argv[])
  17. {
  18.   int sockfd, recvbytes;
  19.   char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
  20.   char snd_buf[MAXDATASIZE];
  21.   struct hostent *host; /* struct hostent
  22.                                      * {
  23.                                      * char *h_name; // general hostname
  24.                                      * char **h_aliases; // hostname's alias
  25.                                      * int h_addrtype; // AF_INET
  26.                                      * int h_length;
  27.                                      * char **h_addr_list;
  28.                                      * };
  29.                                      */
  30.   struct sockaddr_in server_addr;
  31.   int flags;
  32.   int addr_len;

  33.   if (argc < 3)
  34.   {
  35.     printf("Usage:%s [ip address] [any string]\n", argv[0]);
  36.     return 1;
  37.   }

  38.   *snd_buf = '\0';
  39.   strcat(snd_buf, argv[2]);

  40.   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  41.   {
  42.     perror("socket:");
  43.     exit(1);
  44.   }

  45.   server_addr.sin_family = AF_INET;
  46.   server_addr.sin_port = htons(SERVPORT);
  47.   inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
  48.   memset(&(server_addr.sin_zero), 0, 8);
  49.   addr_len = sizeof(struct sockaddr_in);

  50.   /* Setting socket to nonblock */
  51.   flags = fcntl(sockfd, F_GETFL, 0);
  52.   fcntl(sockfd, flags|O_NONBLOCK);

  53.   /* create the connection by socket
  54.    * means that connect "sockfd" to "server_addr"
  55.    * 同步阻塞模式
  56.   */
  57.   if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
  58.   {
  59.     perror("connect");
  60.     exit(1);
  61.   }

  62.   /* 同步非阻塞模式 */
  63.   while (send(sockfd, snd_buf, sizeof(snd_buf), MSG_DONTWAIT) == -1)
  64.   {
  65.     sleep(1);
  66.     printf("sleep\n");
  67.   }
  68.   printf("send:%s\n", snd_buf);


  69.   /* 同步非阻塞模式 */
  70.   while ((recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, MSG_DONTWAIT)) == -1)
  71.   {
  72.     sleep(1);
  73.     printf("sleep\n");
  74.   }

  75.   rcv_buf[recvbytes] = '\0';
  76.   printf("recv:%s\n", rcv_buf);

  77.   close(sockfd);
  78.   return 0;
  79. }


阅读(143) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~