文章目录
一、套接字编程简介
1.1 套接字地址结构
大多数套接字函数都需要一个指向套接字地址结构的指针作为参数。每个协议族都定义它自己的套接字地址结构。这些结构的名字均以**sockaddr_**开头,并以对应每个协议族的唯一后缀结尾。
- IPv4套接字地址结构
以sockaddr_in命名,定义在netinet/in.h中:
struct sockaddr_in{
uint8_t sin_len; //length of structure
sa_family_t sin_family; // AF_INET
in_port_t sin_port; //16-bit TCP or UDP port number
struct in_addr sin_addr; //32-bit IPv4 address
char sin_zero[8]; //unused
};
struct in_addr{
in_addr_t s_addr;
};
注:
(1)ip地址和端口号在套接字地址中总是以网络字节序来存储的
(2)32位ip地址存在两种不同的访问方法。sin_addr按in_addr结构体引用或sin_addr.s_addr按in_addr_t引用
- 通用套接字地址结构
作为函数参数的套接字结构体指针,必须处理来自所支持的任何协议族的套接字地址结构,所以在如何声明所传递指针的数据类型上存在问题。(有了ANSI C后很简单,使用void*即可;然而套接字函数是在之前定义的)。采取的办法是在sys/socket.h头文件中定义一个通用的套接字地址结构:
struct sockaddr{
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[14]; //14 = 2 + 4 + 8
};
- IPv6套接字地址结构
struct sockaddr_in6{
uint8_t sin6_len;
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
struct in6_addr{
uint8_t s6_addr[16];
};
1.2 字节排序函数
大端(big-endian):高字节存储在起始位置
小段(little-endian):低字节存储在起始位置
用联合体(关键代码)判断系统的主机字节序:
union {
short s;
char c[sizeof(short)];
}un;
un.s = 0x0102;
if(sizeof(short) == 2){
if(un.c[0] == 1 && un.c[1] == 2)
//大端
else if(un.c[0] == 2