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);
hhost本地主机to转换nnet网络lunsigned longsunsigned 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最大数据段的大小 |

浙公网安备 33010602011771号