创建套接字
这一章的主要目的是使用 socket
函数来创建套接字:
socket 函数
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
2
3
- domain:套接字使用的协议族信息
- type:套接字数据传输类型信息
- protocol:计算机间通信中使用的协议信息
成功时返回文件描述符,失败时返回 -1
# 2. 套接字协议及其数据传输特性
# 2.1 协议族(Protocol Family)
套接字通信中的协议具有一些分类,通过 socket 函数的第一个参数传递套接字中使用的协议分类信息。此分类信息称为 协议族,分为如下:
头文件 sys/socket.h
中声明的协议族
名称 | 协议族 |
---|---|
PF_INET | IPV4 互联网协议族 |
PF_INET6 | IPV6 互联网协议族 |
PF_LOCAL | 本地通信 Unix 协议族 |
PF_PACKET | 底层套接字的协议族 |
PF_IPX | IPX Novel 协议族 |
# 2.2 套接字类型(Type)
套接字类型指的是套接字的数据传输方式,是通过 socket 函数的第二个参数进行传递。
之所以需要这个参数,是因为 PF_INET 协议族里存在多种数据传输方式。
# 1)socket type 1:面向连接的套接字(SOCK_STREAM)
SOCK_STREAM
:创建面向连接的套接字
传输方式特征整理如下:
- 传输过程中数据不会消失
- 按序传输数据
- 传输的数据不存在数据边界(Boundary)
套接字在收发数据时内部有一个 buffer,可能存在三次接收的数据存在 buffer 中,通过一次 read 就全部读出来,所以说不存在数据边界。接收方 buffer 如果被填满,则发送方会停止发送,不会因此发生数据丢失。
这种套接字连接时发送方和接收方必须一一对应,因此面向连接的套接字可以总结为:
可靠地、按序传递的、基于字节的面向连接的数据传输方式的套接字。
# 2)socket type 2:面向消息的套接字(SOCK_DGRAM)
SOCK_DGRAM
:创建面向消息的套接字。特点如下:
- 强调快速传输而非传输有序
- 传输的数据可能丢失也可能损毁
- 传输的数据有边界
- 限制每次传输数据的大小
相比面向连接的套接字,面向消息的套接字更具传输速度,但可能丢失,特点总结为:
不可靠的、不按序传递的、以数据的高速传输为目的套接字。
# 2.3 协议的最终选择
socket 函数的第三个参数决定最终采用的协议。
有了前面两个,为什么还需要这个参数呢?如果前两个参数可以唯一确定一个协议,那这个参数传递 0 即可。除非遇到“同一协议族中存在多个数据传输方式相同的协议”的情况,才需要指定第三个参数。
“IPv4 协议族”和“面向连接的数据传输”,满足这两个条件的协议只有 IPPROTO_TCP,因此可以使用如下代码创建 TCP 套接字:
int tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
// or
int tcp_socket = socket(PF_INET, SOCK_STREAM, 0);
2
3
SOCK_DGRAM 指的是面向消息的数据传输方式,满足上述条件的协议只有 IPPROTO_UDP,可以使用如下代码创建 UDP 套接字:
int udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
// or
int udp_socket = socket(PF_INET, SOCK_DGRAM, 0;
2
3
# 总结
本章主要介绍了 socket
函数,使用示例如下:
#include <sys/socket.h>
...
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
error_handling("socket() error");
}
2
3
4
5
6
7
8