深入Linux网络编程(一):同步IO


1. IO模型

IO分为同步、异步,阻塞、非阻塞,两两组合成4种模型。

2. 同步阻塞IO

2.1 阻塞的原因

一个常见的问题是IO对请求没有准备好:例如调用读请求的时候可能设备上没有数据,但是将来可能有;调用写请求时可能舍妹没有准备好接收数据,一会儿可能buffer清空就好了。调用过程一般不去理会这些问题,如果程序员仅仅要求在请求返回时工作做好,那么驱动设备就应该阻塞这个请求的进程,使他陷入睡眠状态。

2.2 什么是睡眠

当一个进程处于睡眠态, 意味着它被移除调度队列,直到这个状态被改变之前,CPU都不会处理这个进程。有几个注意事项:

  • 不要在原子上下文中sleep
  • 无法保证精确的睡眠时间
  • 只有在确定其他进程/内核会唤醒自己时,才能睡眠

2.3 同步阻塞IO的编程模型

3. 同步阻塞IO的网络编程代码示例

/* A simple server in the internet domain using TCP
   The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     newsockfd = accept(sockfd, 
                 (struct sockaddr *) &cli_addr, 
                 &clilen);
     if (newsockfd < 0) 
          error("ERROR on accept");
     bzero(buffer,256);
     n = read(newsockfd,buffer,255);
     if (n < 0) error("ERROR reading from socket");
     printf("Here is the message: %s\n",buffer);
     n = write(newsockfd,"I got your message",18);
     if (n < 0) error("ERROR writing to socket");
     close(newsockfd);
     close(sockfd);
     return 0; 
}
  • 1
  • 2
  • 3
  • 下一页

相关内容