socket编程的同步、异步与阻塞、非阻塞示例详解之一

10 篇文章 0 订阅
简介
图 1. 基本 Linux I/O 模型的简单矩阵

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

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

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <netdb.h>
  5. #include <string.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;

  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
*/

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <sys/types.h>
  5. #include <errno.h>
  6. #include <netdb.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #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);
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值