深入理解基本套接字编程

随着网络编程(C/C++)的学习,发现自己对于基本套接字编程有些细节还是不太清楚,然后又查看了对应的书籍和资料,趁着这段时间把这些基础知识梳理了一下,便于自己回顾,同时大家也可以作为参考 :) ~

套接字地址结构

struct in_addr { in_addr_t s_addr; // 32-bit IPv4 address //network byte ordered } struct sockaddr_in { sa_family_t sin_family; //AF_INET in_port_t sin_port; //16-bit TCP or UDP port nummber, network byte ordered struct in_addr sin_addr; //32-bit IPv4 address, network byte ordered char sin_zero[8]; //unused }

  sockaddr_in是网络套接字地址结构,大小为16字节,定义在<netinet/in>头文件中,一般我们在程序中是使用该结构体,但是作为参数传递给套接字函数时需要强转为sockaddr类型,注意该结构体中port和addr成员是网络序的(大端结构)。

struct sockaddr { sa_family_t sa_family; //address family: AF_XXX value char sa_data[14]; //protocol-specific address }

  sockaddr是通过套接字地址结构,当作为参数传递给套接字函数时,套接字地址结构总是以指针方式来使用,比如bind/accept/connect函数等。

htons、ntohs、htonl和ntohl函数

#include <netinet/in.h> uint16_t htons(uint16_t host16bitvalue); uint32_t htonl(uint32_t host32bitvalue); uint16_t ntohs(uint16_t net16bitvalue); uint32_t ntohl(uint32_t net32bitvalue);

  Linux提供了4个函数来完成主机字节序和网络字节序之间的转换。这些函数名字中,h表示host,n表示net,s表示short,l表示long。使用这些函数时,并不关心主机字节序和网络字节序的真实值,也就是为大端还是小端,要做的只是调用适当的函数在主机和网络字节序之间转换为某个特定值。

ient_aton、inet_addr和inet_ntoa函数

#include <arpa/inet.h> int inet_aton(const char *strptr, struct in_addr *addrptr); // 返回:若字符有效则为1,否则为0 in_addr_t inet_addr(const char *strptr); // 返回:若字符串有效则为32位二进制网络字节序地址,否则为INADDR_NONE char *inet_ntoa(struct in_addr inaddr); // 返回:指向一个点分十进制数串的地址

  inet_aton、inet_addr和inet_ntoa在点分十进制数串(比如"192.168.1.1")与它长度为32位的网络字节序二进制值间转换IPv4地址。在调用inet_addr时需特别注意,inet_ntoa函数的输入参数是unsigned int型的ip地址,返回的却是指向ip字符串的指针,很明显,ip字符串所占的内存是在函数内部分配的,而我们并不需要释放该内存,所以,它分配的内存是静态的,内部使用static变量存储IP点分十进制数串,也就是说第二次调用该函数时会覆盖第一次调用该函数时的内存。

inet_pton和inet_ntop函数

#include <arpa/inet.h> int inet_pton(int family, const char *strptr, void *addrptr); // 返回:成功为1,输入不是有效表达式返回0,出错为-1 const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len); // 返回:成功为指向结果的指针,出错为NULL

  这两个函数对于IPv4和IPv6都适用,p代表表达式(presentation)、n表示数值(numeric)。第一个函数尝试转化由strptr指针所指的字符串,通过addptr指针存放二进制结果,成功返回1,如果对指定的family而言输入的不是有效的表达格式,那么返回0

  inet_ntop进行相反的操作,如果len的值太小,不足以存放表达式结果,则返回一个空指针,并置error为ENOSPC。inet_ntop函数的strptr参数不可以是一个空指针,调用者必须为目标存储单元分配内存并制定其大小,调用成功时,这个指针就是该函数返回值。

socket函数

  为了执行网络IO,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型(比如使用IPv4的TCP、使用IPv6的UDP、Unix域字节流协议)和套接字字类型(字节流、数据报或原始套接字)。

#include <sys/socket.h> int socket(int family, int type, int protocol); // 成功返回非负描述符,出错-1

  family指定协议族,type指定套接字类型,protocol指定某个协议类型常值,或者设为0。

family的值有:

AF_INET IPv4协议

AF_INET6 Ipv6协议

AF_LOCAL Unix协议域

AF_ROUTE 路由套接字

AF_KEY 秘钥套接字

type的值有:

SOCK_STREAM 字节流套接字

SOCK_DGRAM 数据报套接字

SOCK_SEQPACKET 有序分组套接字

SOCK_RAW 原始套接字

protocol的值有:

IPPROTO_CP TCP传输协议

IPPROTO_UDP UDP传输协议

IPPROTO_SCTP SCTP传输协议

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/6e5eba01d2a35ae1dd7ecba1d872f6c5.html