Linux IO模型漫谈(3) -- 阻塞式IO实现

简介:

在理解代码前有几个函数先说一下:

1 sockaddr_in 套接字地址结构

1
2
3
4
5
6
7
8
9
10
struct  sockaddr_in {
     uint8_t         sin_len;         //长度字段,这个sockaddr_in结构的长度,一般不用设置和检查它
     sa_family_t     sin_family;      //协议族,TCP,UDP等协议族就设置为AF_INET 
     in_port_t       sin_port;        //端口号
     
     struct  in_addr  sin_addr;        //32位的IPv4地址
     
     char             sin_zero(8);     //未使用
 
}

POSIX规范只需要指定其中的sin_family, sin_port, sin_addr三个字段

这个结构非常重要!!

2 socket函数(创建套接字)

1
2
3
#include <sys/socket.h>
 
int  socket( int  family, int  type, int  protocol)

参数解释:

family:协议族,和sockaddr_in中的sin_family一个意思

type: 指明套接字类型

Protocol:通常赋值为0

 

这个函数是所有套接字编程的入口,创建套接字。

3 htons函数

这个函数是将本地字节序列转换为网络字节序列,简单来说,就是将一个数的高低位互换

(如12 34 -> 3412)

这个函数在给servaddr_in赋值的时候会用到

下面这个程序包含了基本的IO操作,说明以注释的形式加在代码中;

服务器端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>     //这个头包含了最简单的输入和输出
#include <sys/types.h>    //这个头包含了系统调用的大量数据结构
#include <sys/socket.h>   //这个头包含了socket的结构
#include <netinet/in.h>   //这个头包含了internet地址解析的一些数据结构
#include <string.h>
#include <unistd.h>
 
int  main( int  argc, char  *argv[])
{
     int  listenfd, portno;  //文件描述符
     int  clifd, clilen;
     struct sockaddr_in serv_addr,cli_addr;  //socketadd_in定义在netinet/in.h中
     listenfd = socket(AF_INET, SOCK_STREAM, 0 );  //创建一个套接字
     
     bzero(( char  *) &serv_addr, sizeof(serv_addr));  //初始化
     serv_addr.sin_family = AF_INET;     //设置协议族
     serv_addr.sin_port = htons( 7777 );      //设置端口
     serv_addr.sin_addr.s_addr = INADDR_ANY;  //设置socket的另一端的地址信息,由于这里是server程序,因此设置为ANY
     
     bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); //绑定地址,将本地协议地址赋予一个套接字
     listen(listenfd, 5 );  //监听socket,第二个参数规定了内核应该为相应套接字排队的最大连接数个数,不要设置为0
     
     clilen = sizeof(cli_addr);
     clifd = accept(listenfd, (struct sockaddr *) &cli_addr, &clilen); //当有客户端连接的时候,进入连接队列
     
     char  buffer[ 256 ];
     bzero(buffer, 256 );
     read(clifd, buffer, 255 );   //读取客户端发送的消息
     printf( "The Message is:%s\r\n" , buffer);
     
     write(clifd, "I get the message" , 17 ); //往客户端发送消息
     
     close(clifd);
     close(listenfd);
     return  0 ;
 
}

server的流程基本是这样的:

clip_image001

客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
 
int  main( int  argc, char * argv[])
{
     int  socketfd;
     socketfd = socket(AF_INET, SOCK_STREAM, 0 );
         
     struct sockaddr_in serv_addr;
         
     bzero(( char  *)&serv_addr, sizeof(serv_addr));
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_port = htons( 7777 );
         
     connect(socketfd,(struct sockaddr *)  &serv_addr, sizeof(serv_addr));
         
     write(socketfd, "client message" , 14 );
         
     char  buffer[ 256 ];
     bzero(buffer, 256 );
     read(socketfd, buffer, 255 );
         
     printf( "server return message:%s\r\n" , buffer);
         
     return  0 ;
}

客户端的流程如下;

clip_image002






本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2012/06/04/2534178.html,如需转载请自行联系原作者

相关文章
|
1月前
|
网络协议 前端开发 Java
网络协议与IO模型
网络协议与IO模型
网络协议与IO模型
|
1月前
|
安全 NoSQL Java
一文搞懂网络通信的基石✅IO模型与零拷贝
【10月更文挑战第1天】本文深入探讨了网络通信中的IO模型及其优化方法——零拷贝技术。首先介绍了IO模型的概念及五种常见类型:同步阻塞、同步非阻塞、多路复用、信号驱动和异步IO模型。文章详细分析了每种模型的特点和适用场景,特别是多路复用和异步IO在高并发场景中的优势。接着介绍了零拷贝技术,通过DMA直接进行数据传输,避免了多次CPU拷贝,进一步提升了效率。最后总结了各种模型的优缺点,并提供了相关的代码示例和资源链接。
一文搞懂网络通信的基石✅IO模型与零拷贝
|
1月前
|
存储 缓存 算法
如何优化阻塞IO的性能?
【10月更文挑战第6天】如何优化阻塞IO的性能?
38 5
|
1月前
|
开发者
什么是面向网络的IO模型?
【10月更文挑战第6天】什么是面向网络的IO模型?
21 3
|
1月前
|
数据挖掘 开发者
网络IO模型
【10月更文挑战第6天】网络IO模型
38 3
|
1月前
|
缓存 Java Linux
硬核图解网络IO模型!
硬核图解网络IO模型!
|
1月前
|
数据挖掘 开发者
网络IO模型如何选择?
网络IO模型如何选择?【10月更文挑战第5天】
19 2
|
1月前
|
数据库
同步IO模型是一种常见的编程模型
【10月更文挑战第5天】同步IO模型是一种常见的编程模型
20 2
|
2月前
|
存储 机器人 Linux
Netty(二)-服务端网络编程常见网络IO模型讲解
Netty(二)-服务端网络编程常见网络IO模型讲解
基于套接字的IO模型
基于套接字的IO模型