socket
字节顺
网络字节顺NBO(Network Byte Order)
大端模式
(big-endian),按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题;
主机字节顺序(HBO,Host Byte Order)
小端模式
,不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。
如 Intel x86结构下,short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12
字节顺转换
#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);
h
host
本地主机to
转换n
net
网络l
unsigned long
s
unsigned short
ntohs()
简述:
将一个无符号短整形数从网络字节顺序转换为主机字节顺序。
#include <winsock.h>
u_short PASCAL FAR ntohs( u_short netshort);
netshort
:一个以网络字节顺序表达的16位数。
注释:
本函数将一个16位数由网络字节顺序转换为主机字节顺序。
返回值
:ntohs()
返回一个以主机字节顺序表达的数
ntohl()
简述:
将一个无符号长整形数从网络字节顺序转换为主机字节顺序。
#include <winsock.h>
u_long PASCAL FAR ntohl( u_long netlong);
netlong
:一个以网络字节顺序表达的32位数。
注释:
本函数将一个32位数由网络字节顺序转换为主机字节顺序。
返回值
:
ntohl()
返回一个以主机字节顺序表达的数。
htons()
简述:
将主机的无符号短整形数转换成网络字节顺序。//将无符号短整型主机字节序转换为网络字节序
#include <winsock.h>
u_short PASCAL FAR htons( u_short hostshort);
hostshort
:主机字节顺序表达的16位数。
注释:
本函数将一个16位数从主机字节顺序转换成网络字节顺序。
返回值
:
htons()
返回一个网络字节顺序的值。
简单地说,htons()
就是将一个数的高低位互换
(如:12 34 --> 34 12)
VB表示:
MsgBox Hex(htons(&H1234))
显示值为 3412
htonl()
简述:
将主机的无符号长整形数转换成网络字节顺序。//将无符号长整型网络字节序转换为主机字节序
#include <winsock.h>
u_long PASCAL FAR htonl( u_long hostlong);
hostlong
:主机字节顺序表达的32位数。
注释:
本函数将一个32位数从主机字节顺序转换成网络字节顺序。
返回值
:
htonl()
返回一个网络字节顺序的值
网络地址字节顺转换
inet_addr()
简述:
将一个点间隔地址转换成一个in_addr。
#include <winsock.h>
unsigned long PASCAL FAR inet_addr( const struct FAR* cp);
cp
:一个以Internet标准“.”间隔的字符串。例如202.38.214.xx
当IP地址为255.255.255.255是被认为无效IP地址。
本函数解释cp参数中的字符串,这个字符串用Internet的“.”间隔格式表示一个数字的Internet地址。
返回值
:
一个无符号长整形数,可用作Internet地址。所有Internet地址以网络字节顺序返回(字节从左到右排列)
inet_ntoa()
简述:
将网络地址转换成“.”点隔的字符串格式。
#include <winsock.h>
char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
in
:一个表示Internet主机地址的结构。
注释:
本函数将一个用in参数所表示的Internet地址结构转换成以“.” 间隔的诸如“a.b.c.d”的字符串形式。当IP地址为255.255.255.255是认为有效IP地址。这是与inet_addr()
的区别
返回值
:
若无错误发生,inet_ntoa()
返回一个字符指针。否则的话,返回NULL。
inet_aton()
与inet_ntoa()作用相反
inet_pton()
简述:
本函数将点分十进制转换为整数
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);
这个函数转换字符串到网络地址,第一个参数af是地址族,转换后存在dst中
inet_pton
是inet_addr
的扩展,支持的多地址族有下列:
af = AF_INET
src
为指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函数将该地址
转换为in_addr的结构体,并复制在dst中
af =AF_INET6
src为指向IPV6的地址,,函数将该地址转换为in6_addr的结构体,并复制在dst中
如果函数出错将返回一个负值,并将errno设置为EAFNOSUPPORT,如果参数af指定的地址族和src格式不对,函数将返回0
inet_ntop()
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
这个函数转换网络二进制结构到ASCII类型的地址,参数的作用和上面相同,只是多了一个参数socklen_t cnt,他是所指向缓存区dst的大小,避免溢出,如果缓存区太小无法存储地址的值,则返回一个空指针,并将errno置为ENOSPC
atoi()
array to integer将字符串转换为整形数
协议族
结构体
sockaddr
头文件
#include <sys/socket.h>
中定义,sockaddr
的缺陷是:sa_data把目标地址和端口信息混在一起了
struct sockaddr{
sa_family_t sin_family;//地址族
char sa_data[14];//14字节,包含套接字中的目标地址和端口信息
};
sockaddr_in
sockaddr_in
在头文件#include<netinet/in.h>
或#include <arpa/inet.h>
中定义,该结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中
struct sockaddr_in{
sa_family_t sin_family; //地址族
uint16_t sin_port; //16wug TCP/UDP端口号,必须是网络字节序(NBO)
struct in_addr sin_addr; //32位IP地址,
char sin_zero[8]; //不使用
};
struct in_addr{
In_addr_t s_addr; //32位IPv4地址,必须是网络字节序(NBO)
};
- 二种结构体都是16个字节,占用内存大小一致,可相互转换。
sockaddr
常用于bind、connect、recvfrom、sendto
等函数的参数,指明地址信息,是一种通用的套接字地址sockaddr_in
是internet环境下套接字的地址形式。所以在网络编程中我们会对sockaddr_in
结构体进行操作,使用sockaddr_in
来建立所需的信息,最后使用类型转化就可以了。一般先把sockaddr_in
变量赋值后,强制类型转换后传入用sockaddr
做参数的函数:sockaddr_in
用于socket
定义和赋值;sockaddr
用于函数参数
套接字选项
getsockopt & setsockopt
getsockopt
和setsockopt
两个函数来获取和设置套接口的选项
getsockopt()
用于获取任意类型、任意状态套接口的选项当前值,并把结果存入optval
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
setsockopt()
用于任意类型、任意状态套接口的设置选项值
#include <sys/socket.h>
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
返回值
若成功返回0,若出错返回-1,errno被设为以下的某个值
EBADF:sock不是有效的文件描述词
EFAULT:optval指向的内存并非有效的进程空间
EINVAL:在调用setsockopt()时,optlen无效
ENOPROTOOPT:指定的协议层不能识别选项
ENOTSOCK:sock描述的不是套接字
参数
sockfd:标识一个套接口的描述字。
level:选项定义的层次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6等。
optname:需设置的选项。
optval:指针,指向存放选项值的缓冲区。
optlen:optval缓冲区长度。
level&optname
- level级别:SOL_SOCKET(通用套接字选项)
optname(选项名) | 选项值数据类型 | 访问 | 说明 |
---|---|---|---|
SO_ACCEPTCONN | bool | get | 如为TRUE(真) ,表明套接字处于监听模式 |
SO_BROADCAST | bool | get/set | 如TRUE,表明套接字已配置成对广播消息进行发送 |
SO_CONNECT_TIME | int | get | 返回套接字建立连接的时间,以秒为单位,如尚未连接,返回0xffffffff |
SO_DEBUG | bool | get/set | 如果TRUE,就允许调试输出 (W32不支持) |
SO_DONTLINGER | bool | get/set | 如果是TRUE,则禁用SO_LINGER |
SO_LINGER | struct linger | get/set | 设置或获取当前的拖延值 |
SO_DONTROUTE | bool | get/set | 如果TRUE,便直接向网络接口发送消息,毋需查询路由表 |
SO_ERROR | bool | get | 返回错误状态 |
SO_EXCLUSIVEADDRUSE | bool | get/set | 如果TRUE,套接字绑定那个本地端口就不能重新被另一个进程使用 |
SO_KEEPALIVE | bool | get/set | 如果TRUE,套接字就会进行配置,在会话过程中发送”保持活动”消息 |
SO_MAX_MSG_SIZE | unsigned int | get | 对一个面向消息的套接字来说,一条消息的最大长度 |
SO_OOBINLINE | bool | get/set | 如果是TRUE,带外数据就会在普通数据流中返回 (W32不支持) |
SO_PROTOCOL_INFO | WSAPROTOCOL_INFO | get | 套接字绑定的那种协议的特征 |
SO_RCVBUF | int | get/set | 面向接收操作,为每个套接字分别获取或设置缓冲区长度 |
SO_REUSEADDR | bool | get/set | 是TRUE,套接字就可与一个正由其他套接字使用的地址绑定到一起,或与处在TIME_WAIT状态的地址绑定到一起 |
SO_SNDBUF | bool | get/set | 设置分配给套接字的数据发送缓冲区的大小 |
SO_TYPE | int | ||
SO_SNDTIMEO | int | get/set | 获取或设置套接字上的数据发送超时时间(以毫秒为单位) |
SO_RCVTIMEO | int | get/set | 获取或设置与套接字上数据接收对应的超时时间值(以毫秒为单位) |
SO_UPDATE_ACCEPT_CONTEXT | SOCKET | get/set | 更新SOCKET状态 |
- level级别:IPPROTO_IP
optname(选项名) | 选项值数据类型 | 访问 | 说明 |
---|---|---|---|
IP_OPTINS | char[] | get/set | 设置或获取IP头内的IP选项 |
IP_HDRINCL | bool | get/set | 如果是TRUE,IP头就会随即将发送的数据一起提交,并从读取的数据中返回 |
IP_TOS | int | get/set | IP服务类型 |
IP_TTL | int | get/set | IP协议的“存在时间” (TTL) |
IP_MULTICAST_IF | unsigned long | get/set | 获取或设置打算从它上面发出多播数据的本地接口 |
IP_MULTICAST_TTL | int | get/set | 为套接字获取或设置多播数据包的存在时间 |
IP_MULTICAST_LOOP | bool | get/set | 如果TRUE,发至多播地址的数据将原封不动地“反射”或“反弹”回套接字的进入缓冲区 |
IP_ADD_MEMBERSHIP | struct ip_mreq | set | 在指定的IP组内为套接字赋予成员资格 |
P_DROP_MEMBERSHIP | struct ip_mreq | set | 将套接字从指定的IP组内删去(撤消成员资格) |
IP_DONTFRAGMENT | bool | get/set | 如果是TRUE,就不对IP数据报进行分段 |
struct ip_mreq{
struct in_addr imr_multiaddr;//多播组的IP地址
struct in_addr imr_interface;//加入的客户端主机IP地址
}
- level级别:IPPROTO_TCP
optname(选项名) | 选项值数据类型 | 访问 | 说明 |
---|---|---|---|
TCP_NODELAY | bool | get/set | 若为TRUE, 就会在套接字上禁用Nagle算法 (只适用于流式套接字) |
TCP_MAXSEG | int | get | TCP最大数据段的大小 |