1.什么是socket?
Socket 可以看成是用户进程与内核网络协议栈的编程接口。
Socket 既可以用于本机的进程间通信,也可用于网络上不同主机的进程间通信。
Socket可用于异构系统之间的通信,异构系统是指不同的架构系统或不同的操作系统,所以在微服务架构下,不同APP之间更多的采用Socket通信机制(或者封装了Socket 通信的上层进程间通信机制)。
2. IPv4 套接字地址结构
通常也称为“网际套接字地址结构”。
头文件:<netinet/in.h>
struct in_addr
{
in_addr_t s_addr; //32 bit IPv4 address
} //network byte order
struct sockaddr_in {
short sin_family; // 2 bytes e.g. AF_INET, AF_INET6
unsigned short sin_port; // 2 bytes e.g. htons(3490)
struct in_addr sin_addr; // 4 bytes see struct in_addr,
char sin_zero[8]; // 8 bytes zero this if you want to
};
结构体中的 port 和IP address都是网络字节序,即大端模式。
3. 通用套接字地址结构。
为什么会有通用套接字地址结构呢?
因为套接字针对的是一个协议族,并不单单是TCP,UDP。
与 sockaddr_in 长度一样,都是16个字节,即占用的内存大小是一致的,因此可以互相转化。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。
sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息,是一种通用的套接字地址。
struct sockaddr {
unsigned short sa_family; // 2 bytes address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
4. 字节序
4.1 大端字节序(big endian)
高位字节存储于低位内存地址
4.2 小端字节序 (small endian)
高位字节序存储于高位内存地址
4.3 主机字节序
不同主机的字节序不同
4.4 网络字节序
规定为大端字节序
与字节序转换相关的函数有:
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
code中, h 代表 host; n代表 network; s 代表 short; l 代表 long。
htonl : host to network long,将主机 unsigned int 型数据转换成网络字节顺序;
htons : host to network short ,将主机 unsigned short 型数据转换成网络字节顺序;
ntohl、ntohs 的功能分别与 htonl、htons 相反。
5. 地址转换函数
#include <arpa/inet.h>
/* Convert Internet host address from numbers-and-dots notation in CP
into binary data and store the result in the structure INP. */
int inet_aton (const char *__cp, struct in_addr *__inp);
/* Convert Internet host address from numbers-and-dots notation in CP
into binary data in network byte order. */
in_addr_t inet_addr (const char *__cp);
/* Convert Internet number in IN to ASCII representation. The return value
is a pointer to an internal array containing the string. */
char *inet_ntoa (struct in_addr __in);
inet_aton将__cp指向的字符串转成网络序的地址存在__inp指向的地址结构。成功返回1,否则返回0。(据书中所说,如果__inp指针为空,那么该函数仍然对输入字符串进行有效性检查但是不存储任何结果)
inet_addr功能和inet_aton类似,但是inet_addr出错时返回INADDR_NONE常值(通常是32位均为1的值),这就意味着至少有一个IPv4的地址(通常为广播地址255.255.255.255)不能由该函数处理。建议使用inet_aton代替inet_addr。
inet_ntoa将网络序二进制IPv4地址转换成点分十进制数串。该函数的返回值所指向的字符串驻留在静态内存中。这意味着该函数是不可重入的。同时我们也该注意到该函数以一个结构体为参数而不是常见的以一个结构体指针作为参数。
6. 套接字类型有哪些?
- 流式套接字: TCP(SOCK_STREAM)
提供面向连接的,可靠的数据传输服务,数据无差错,无重复,按序接收 - 数据报套接字:UDP(SOCK_DGRAM)
无连接服务,数据可能丢失,重复。顺序混乱。 - 原始套接字:(SOCK_RAW)