一、套接字编程简介
1. socket套接字
套接字编程:网络通信程序的编写。
套接字:
操作系统向上层提供的用于实现网络通信实现的统称。
2. 网络通信
网络通信其实都是网络中两台主机之间的通信;其中一端叫做客户端,一端叫做服务端:
服务端:针对用户请求提供服务的一端;是被动接收请求的一端。
客户端:用户的一端;是主动发出请求的一端。
3. 传输层协议:TCP&UDP
TCP:传输控制协议,面向连接,可靠传输。面向字节流;
应用于对安全性要求大于实时性要求的场景。例:文件传输、
UDP:用户数据报协议,无连接,不可靠,面向数据报。
应用于对实时性要求大于安全性要求的场景。例:视频、音频、
二、UDP通信程序编写
1.服务端流程
1.1 创建套接字
在内核中创建socket结构体,将进程与网卡关联起来。
1.2 为套接字绑定地址信息
给创建的套接字socket结构体描述源端地址信息。
作用:
1)告诉系统,网卡收到的那条数据应该交给我来处理;
2)当发生数据时,使用绑定的地址信息作为源端地址信息。
1.3 接收数据
从socket的接收缓冲区中取出数据。
1.4 发送数据
把要发送的数据放到发送缓冲区中。
1.5 关闭套接字
2.客户端流程
2.1 创建套接字
2.2 为套接字绑定地址信息(不推荐)
客户端并不推荐主动绑定地址。
原因:
1)绑定之后,程序只能启动一个;
2)客户端并不需要固定使用某个地址。
2.3 向服务器发送数据
发送数据前,若socket没有绑定指定地址,则系统会自动选择一个合适的地址信息进行绑定。
2.4 接收数据
2.5 关闭套接字
三、套接字相关接口
1. 创建套接字
int socket(int domain, int type, int protocol);
domain:地址域类型:
ipv4: AF_INET;
ipv6:AF_INET6;
type:套接字类型:
SOCK_STREAM:提供字节流传输服务;
SOCK_DGRAM:提供数据报传输服务;
protocol:协议类型:
0:默认类型;
TCP:IPPROTO_TCP;
UDP:IPPROTO_UDP;
返回值:
成功,返回一个套接字描述符;失败,返回-1。
2. 绑定地址信息
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:创建套接字返回的描述符;
addr:要绑定的地址信息结构(需要自己封装):
ipv4:struct sockaddr_in;
ipv6:struct sockaddr_in6;
addrlen:地址信息长度;
返回值:
成功,返回0;失败,返回-1。
例:
bind会根据用户封装的地址信息的第一个sa_family成员,来判断其类型。
3. 发送数据
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
sockfd:套接字描述符;
buf:要发送的数据的空间首地址;
len:要发送的数据长度;
flags:选项标准 0-默认阻塞发送;
dest_addr:对端地址信息
addrlen:地址信息长度;
返回值:
成功,返回实际发送的数据的字节长度;失败,返回-1。
4. 接收数据
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
sockfd:套接字描述符;
buf:一块空间首地址,用于存放从内核获取到的数据;
len:要获取的数据长度;
flags:默认0-阻塞接收;
src_addr:当前接收数据的发送方的地址信息;
*addrlen:这是一个输入输出型参数,指定想要多长的地址,返回实际长度;
返回值:
成功,返回实际接收到的数据长度;失败,返回-1。
5. 关闭套接字
int close(fd);
fd:套接字描述符。
四、字节序转换接口
#include<arpa/inet.h>
1. 主机字节序—>网络字节序
uint32_t htonl(uint32_t hostlong);
主机字节序—>网络字节序;针对类型32位。
uint16_t htons(uint16_t hostshort);
主机字节序—>网络字节序;针对类型16位。
2. 网络字节序—>主机字节序
uint32_t ntohl(uint32_t netlong);
网络字节序—>主机字节序;针对类型32位。
uint16_t ntohs(uint16_t netshort);
网络字节序—>主机字节序;针对类型16位。
3. 字符串IP地址字节序转换
3.1 字符串IP地址—>网络字节序的整数IP地址
int_addr_t inet_addr(const char *cp); int inet_pton(int af, const char *src, void *dst); ipv4:af = AF_INET; ipv6:af = AF_INET6;
3.2 网络字节序的整数IP读者—>字符串IP地址
char *inet_ntoa(struct in_addr addr);
注:此函数中用的是静态的空间存放字符串IP地址。
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); ipv4:af = AF_INET; ipv6:af = AF_INET6;