2. 套接字类型与协议设置
2. 套接字类型与协议设置
[!quote]
协议就是为了完成数据交换而定好的约定
创建套接字
[!quote]
create an endpoint for communication
命令: man 2 socket
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);domain
[!quote]
this selects the protocol family which will be used for communication.
| Name | Purpose | 地址示例 | 用途 | 说明 |
|---|---|---|---|---|
| AF_INET | IPv4互联网协议族 | 10.0.2.15 | ||
| AF_INET6 | IPv6 | fe80::5506:f276:a82b:aab6%20 | ||
| AF_LOCAL, AF_UNIX | Local communication | /tmp/mysocket | 本地进程间通信 | |
| AF_PACKET | Low level packet interface | 00:22:15:56:0b:54 网卡mac 地址,windows 可以在powershell 中使用getmac 查看。linux 使用ifconfig命令,HWaddr 08:00:27:fe:8b:f8 | 抓包工具 | linxu特有,以获取到所有经过数据链路层的帧 |
使用Winpacp、Npacp 抓包是通过驱动提供的接口获取到帧。
关于AF 与 PF
书中名称为PF(protocol family),使用man 查看帮助中的参数名称AF(address family)
两者值是一样的
使用AF,在表现上是通过地址进行区分。
type
[!quote]
specifies the communication semantics
| Name | Purpose |
|---|---|
| SOCK_STREAM | Provides sequenced, reliable, two-way, connection-based byte streams. |
| SOCK_DGRAM | Supports datagrams (connectionless, unreliable message of a fixed maximum length) |
| SOCK_RAW | Provides raw network protocol access |
面向连接的套接字 SOCK_STREAM
特点:
- sequence: 数据带有序号;接收顺序和发送顺序一致
- reliable:数据内容不会出错
- two-way:双向通讯,客户端、服务端都可以同时发送、接收数据
- connection based:通讯前需要先连接连接;一对一进行通讯
- byte streams:字节流。不存在数据边界(Boundary)
byte streams 的具体含义:
发送方多次发送的数据,接收方可以1字节1字节读取,也可以2字节,3字节。。
接收方没办法根据读取到的字节数量(也相当于读取次数)判断是否接收了多少到了多少包以及包时候完整。
在接收方看来,包与包之间没有间隔(没有数据边界)
需要自己定义报文的分割方式。
流:流动、连续
缓冲区
socket 内有接收、发送缓冲(字节数组)
[!quote]
接收缓冲区满时,传输端套接字将停止传输。面向连接的套接字会根据接收端的状态传输数据。
面向消息的套接字 SOCK_DGRAM
特点:
- connectionless: 不需要建立连接,直接发送、接收数据
- unreliable: 不可靠。可能发生数据丢失、出错、重复。发送的顺序和接收的顺序不一致。
- fixed maximum length:固定的最大长度。限制单条数据报的最大长度。每次发送的数据是一个完整的数据报(datagram)
- 传输速度快
protocol
[!quote]
The protocol specifies a particular protocol to be used with the socket.
| domain | type | protocol |
|---|---|---|
| AF_INET | SOCK_STREAM | IPPROTO_TCP |
| AF_INET | SOCK_DGRAM | IPPROTO_UDP |
| AF_INET | SOCK_RAW | IPPROTO_ICMP, IPPROTO_IGMP... |
通常通过domain 和 type 即可确定protocol,但是如果有多个protocol可用时需要protocol参数指定使用的protocol
唯一确定时protocol 使用0
测试TCP 的 无数据边界特性
服务端一次发送13字节数据,客户端read读取单个字节,应该调用13次read。
while(read_len = read(sock, &message[idx++], 1))
{
//printf("read_len:%d\n", read_len);
if(read_len == -1)
unix_error("read() error!");
str_len += read_len;
}
printf("read_len:%d\n", read_len);
printf("Message from server :%s\n", message);
printf("Function read call count: %d\n", str_len);效果:
read_len:0
Message from server :Hello World!
Function read call count: 13如果使用网络调试助手,在client 连接成功后,服务端发送数据。然后关闭服务端,client read返回0.
如果不关闭服务端,那么read阻塞,一直等待数据。
练习
6:多次发送一次读取
在server中多次发送数据,client 一次性读取到全部数据。
验证:多包数据可能在传输前合并为一包数据
提示server中每次write 后 执行多余操作(printf)进行延时