1、网络字节序
已知:内存中的很多数据都有大小端之分,在网络这,网络数据流也是有大小端之分的。
TCP/IP协议规定:网络数据流采用大端字节序(即低地址处放高位字节)。
因此,小端机器发送网络数据流之前,必须转为大端(一般的机器会自动转换):
在网络-本地字节序转换这用到如下接口:
#include <arpa/inet.h>
用于端口格式转换:
h:host表示本地字节序。
n:network表示网络字节序。
uint32_t htonl(uint32_t hostlong); | 32位的本地字节序转为网络字节序。 |
uint16_t htons(uint16_t hostshort); | 16位的本地字节序转为网络字节序。 |
uint32_t ntohl(uint32_t netlong); | 32位的网络字节序转为本地字节序。 |
uint16_t ntohs(uint16_t netshort); | 16位的网络字节序转为本地字节序。 |
用于IP地址格式转换:
in_addr_t inet_addr(const char *cp); | 将本地格式的IP,转换成in_addr_t类型的IPv4地址,并返回 |
2、socket编程接口
2.1、sockaddr结构
socket API 是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4,IPv6等,然而各种网络协议的地址格式并不相同。
但是,为了保证编码统一,我们就需要使用同一个接口,既可以实现网络通信,又可以实现本地通信。
这就C语言版本的多态:
使用同一个struct sockaddr,通过对象的第一个字段,来区分是本地通信还是网络通信。
2.2、sockaddr_in结构 -- 网络通信
sockaddr结构:
struct sockaddr
{__SOCKADDR_COMMON (sa_); // Common data: address family and lengthchar sa_data[14]; // Address data
};
sockaddr_in结构:
struct sockaddr_in
{__SOCKADDR_COMMON (sin_);in_port_t sin_port; // portstruct in_addr sin_addr; // Internet address.....
};
其中in_addr结构:
typedef uint32_t in_addr_t;
struct in_addr
{in_addr_t s_addr; // IPv4的IP地址, 其实就是一个32位的整数
};
我们接下来在使用socket进行编程的时候,主要是基于IPv4进行编程,主要使用三部分信息:地址类型、端口号、IP地址。
2.3、socket通信的本质
之后我们通过socket函数,创建套接字,本质上就是创建了一个文件!!
网络通信的本质,就是基于这个文件进行数据交互。
3、socket编程流程
3.1、创建socket套接字网络文件
int socket(int domain, int type, int protocol);
3.1.1、返回值
On success, a file descriptor for the new socket is returned. On error, -1 is returned, and errno is set a