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_ptoninet_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

getsockoptsetsockopt两个函数来获取和设置套接口的选项

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最大数据段的大小
posted @ 2021-09-14 21:47  wangzhilei  阅读(57)  评论(0编辑  收藏  举报