创建套接字
在内核中创建struct socket结构体,使进程与网卡之间建立联系
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
- domain:地址域
AF_INET——IPv4地址域 - type:套接字类型
SOCK_STREAM——流式套接字
SOCK_DGRAM——数据报套接字 - proto:传输层协议类型
0 :默认 是依据type默认,流式则tcp,数据报则udp
IPPROTO_TCP——对应数字6
IPPROTO_UDP——对应数字17 - 返回值:套接字操作句柄-----文件描述符
为套接字绑定地址信息
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
- sockfd:套接字套作句柄,创建socket函数的返回值
- my_addr:地址信息结构, 用于描述内核中socket所使用的地址信息
- addrlen : 地址信息结构的长度
- IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位地址类型, 16位端口号和32位IP地址.
- IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6. 这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容.
- socket API可以都用struct sockaddr *类型表示, 在使用的时候需要强制转化成sockaddr_in; 这样的好处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数;
接收数据
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
从sockfd对应的socket结构体中的接收队列中取出一条数据放到buf中
- sockfd:指定socket操作句柄, 从哪个socket的接受缓冲区取出数据
- buf:用户态缓冲区, 用于存放从内核拷贝出来的数据
- len:想要获取的数据长度, 此长度不能大于buf的长度
- flag:默认为 0 阻塞接受, 缓冲区没有数据则阻塞等待
- src_addr:输出型参数——用于获取发送这个数据的源端地址信息结构
- add_len:输入输出型参数, 用于指定想要获取多长的地址信息, 并用于返回实际获取的地址长度
- 返回值:成功返回实际接收到的数据长度, 失败返回 - 1
发送数据
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
将buf中len长度的数据通过socket绑定socketfd对应的socket结构中的ip/端口将数据发送到dest_addr地址的主机上
- sockfd:指定套接字描述符
- buf: 要发送的数据首地址
- len:要发送的数据长度
- flag:选项参数, 默认为 0 表示若缓冲区数据已满则阻塞发送数据并等待
- dest_addr:目的端的首地址
- addr_len : 地址信息结构长度
- 返回值:成功返回实际发送的数据字节长度, 失败返回 - 1
关闭套接字
int close(int fd);
- fd:套接字操作句柄
经常使用的主机字节序、网络字节序、点分十进制ip转化函数
#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);
- 将点分十进制字符串ip地址转换为网络字节序ip地址
in_addr_t inet_addr(const char* cp);
- 将网络字节序ip地址转换为点分十进制字符串ip地址
char* inet_ntoa(struct in_addr in);