一、主机字节序列和网络字节序列
主机字节序列分为大端字节序列和小端字节序列,不同的主机采用的字节序列可能不同。大端字节序列是指一个整数的高位字节存储在内存的低地址处,低位字节存储在内存的高地址处。小端字节序列是指整数的高位字节存储在内存的高地址处,低位字节存储在内存的低地址处。在两台使用不同字节序列的主机之间传递数据时,可能会出现冲突。所以,在将数据发送到网络时规定整型数据使用大端字节序列,所以也把大端字节序列称为网络字节序列。对方接收到数据后,可以根据自己的字节序列转换。
Linux系统提供如下4个函数来完成主机字节序列和网络字节序列的转换:
二、套接字的地址结构
1.通用socket地址结构
socket网络编程接口中表示socket地址的是结构体sockaddr,定义如下:
#include<bits/socket.h>
struct sockaddr
{
sa_famliy_t sa_family;
char sa_data[14];
}
sa_family成员是地址族(sa_famliy_t)类型的变量。地址族类型通常与协议族类型对应。常见的协议族和对应的地址族如下图所示:
2.专用socket地址结构
TCP/IP协议族有sockaddr_in和sockaddr_in6两个专用的socket地址结构,它们分别用于IPV4和IPV6,一般使用sockaddr_in:
结构体sockaddr_in它用来处理网络通信的地址,是internet环境下套接字的地址形式。
所以在网络编程中我们会对sockaddr_in结构体进行操作,使用sockaddr_in来建立所需的信息,最后使用类型转化就可以了。sockaddr_in用于socket定义和赋值。
struct sockaddr_in
{
sa_family_t sin_family;//地址族 AF_INET
u_int16_t sin_port;//端口号,需要用网络字节序表示
struct in_addr sin_addr;//IPV4地址结构体
}
该结构体中提到的另一个结构体 in_addr 的定义如下:
struct in_sddr
{
u_int32_t s_addr;//以网络字节序列表示IPV4地址
}
它用来表示一个32位的IPv4地址。
in_addr_t 一般为 32位的unsigned int,其字节顺序为网络顺序,即该无符号整数采用大端字节序 。
3.IP地址转换函数
通常,人们习惯用点分十进制字符串表示IPV4地址,但编程中我们需要先把它们转化为整数方能使用,下面函数可用于点分十进制字符串表示的IPV4地址和网络字节序整数表示的IPV4地址之间的转换:
三、网络编程接口
1.socket()创建套接字
参数解释:
第一个参数domain:设置套接字的协议簇, AF_UNIX AF_INET AF_INET6。
第二个参数type:设置套接字的服务类型,SOCK_STREAM(流式套接字)、SOCK_DGRAM(数据报格式套接字)。
第三个参数protocol:一般设置为0,表示使用默认协议
返回值:创建成功返回套接字的文件描述符,失败返回-1 。
2.bind()服务端把用于通信的地址和端口绑定到 socket 上
参数解释:
第一个参数sockfd:套接字文件描述符,即代表socket函数创建的套接字文件。
第二个参数addr:指向一个struct sockaddr类型的结构体变量,此结构体成员用于设置要绑定的ip和端口。
struct sockaddr结构体如下:
struct sockaddr {
sa_family_t sa_family;//指定协议族
char sa_data[14];//字符数组,存放ip和端口
}
由于一般在定义套接字地址的时候用的是struct sockaddr_in类型的结构体变量,所以在这个参数中要把struct sockaddr_in类型的结构体变量强转为struct sockaddr类型的结构体变量。原因是:struct sockaddr_in结构体的成员中设置ip和端口的变量是分开的,所以在定义的时候设置方便,但是bind函数要求的是struct sockaddr类型的结构体变量,所以使用struct sockaddr_in设置套接字地址以后要将其强制转化为struct sockaddr类型,然后通过这个参数传值给bind函数。
第三个参数addrlen:第二个参数所指向的结构体变量的大小,即socket地址的长度。
返回值:成功返回0,失败返回-1。
3.listen()创建一个监听队列以存储待处理的客户连接
参数解释:
第一个参数sockfd:被监听的socket套接字。
第二个参数backlog:表示处于完全连接状态的socket的上限。
返回值:成功返回0,失败返回-1。
4.accept()从listen监听队列中接收一个连接
参数解释:
第一个参数sockfd:是执行过listen系统调用的监听socket 。
第二个参数addr:参数用来获取被接受连接的远端socket地址。
第三个参数addrlen:指定该socket地址的长度。
返回值:成功返回一个新的连接socket,该socket唯一地标识了被接收的这个连接,失败返回-1 。
5.connect()客户端需要通过此系统调用来主动与服务器建立连接
参数解释:
第一个参数sockfd:由socket()返回的一个socket。
第二个参数serv_addr:服务器监听的socket地址。
第三个参数addrlen:指定这个地址的长度。
返回值:成功返回0,失败返回-1。
6.recv()读取sockfd上的数据(TCP读取数据)
参数解释:
第一个参数sockfd:已连接stocket的描述符。
第二个参数buff:指定读缓冲区的位置。
第三个参数len:指定读缓冲区的大小。
第四个参数flags:为数据收发提供了额外的控制。
7.send()往socket上写入数据(TCP写入数据)
参数解释:
第一个参数sockfd:已连接stocket的描述符。
第二个参数buff:指定读缓冲区的位置。
第三个参数len:指定读缓冲区的数据长度。
第四个参数flags:为数据收发提供了额外的控制。
8.close()关闭一个连接
参数解释:
参数sockfd:关闭该连接对应的socket。