网络编程常用函数
一、字节序转换/点分与十进制转换
大小端概念:
大端:高地址放低位数据
小端:高地址放高位数据
地址高低:越往后地址位越高
数据高低:越往后数据位越低
例如
union {
int num;
char buf[4];
}u1;
u1.num=0x12345678
大端:
&buf[0]=0x4000 buf[0]=0x12 //低地址 高数据
&buf[1]=0x4001 buf[1]=0x34
&buf[2]=0x4002 buf[2]=0x56
&buf[3]=0x4003 buf[3]=0x78 //高地址 低数据
小端:
&buf[0]=0x4000 buf[0]=0x78 //低地址 低数据
&buf[1]=0x4001 buf[1]=0x56
&buf[2]=0x4002 buf[2]=0x34
&buf[3]=0x4003 buf[3]=0x12 //高地址 高数据
网络字节序是大端字节序(低地址存放更高位的字节)所以,对于字节序为小端的机器需要收发网络数据的场景,要对这些数据进行字节序转换。
字节序转换函数,常用的有四个:
uint32_t htonl(uint32_t hostlong)
将32位整数由主机字节序转为网络字节序
uint16_t htons(uint16_t hostshort)
将16位整数由主机字节序转为网络字节序
uint32_t ntohl(uint32_t netlong)
将32位整数由网络字节序转为主机字节序
uint16_t htons(uint16_t hostshort)
将16位整数由网络字节序转为主机字节序
其他点分制与十进制转化:
int inet_pton(int family, const char *strptr, void *addrptr)
将点分制转为大端十进制写入到addrptr中,实际输入为sockaddr_in.sin_addr的地址
char *inet_ntoa(struct in_addr in);
将大端十进制转为小端点分制字符串
二、socket类
int socket(int af,int type,int protocol);
@af:
Address Family ip地址类型:
AF_INET(IPv4)
AF_INET6(IPv6)
127.0.0.1 代表这本机localhost
@type:
连接类型:
SOCK_STREAM(流格式套接字/面向连接的套接字)TCP
SOCK_DGRAM(数据报套接字/无连接套接字)UDP
SOCK_RAW 原始套接字允许对底层协议如IP、ICMP直接访问,主要用于新网络协议测试
SOCK_SEQPACKET 长度固定、有序、可靠的面向连接报文传递
@protocol
传输协议:
IPPROTO_TCP
IPPTOTO_UDP
return:文件描述符
error:INVALID_SOCKET=-1
success:>0
一般使用listenfd
@sockfd:
创建的套接字的文件描述符 一般为监听fd
@addr:
本地协议地址的结构体 sockaddr 的指针
一般使用sockaddr_in强制转化为sockaddr结构体指针
@addrlen:
sockaddr结构体长度
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
@struct sockaddr 可指向sockaddr_in且一个字符串拆成多个成员,更 用以使用
@ struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
@struct sockaddr_in {
short int sin_family; //Address family
unsigned short int sin_port; //Port number
struct in_addr sin_addr; //Internet address
unsigned char sin_zero[8]; //Same size as struct sockaddr
};
$window:<winsock.h>定义:{
@struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
};
#define s_addr S_un.S_addr //can be used for most tcp & ip code
#define s_host S_un.S_un_b.s_b2 //host on imp
#define s_net S_un.S_un_b.s_b1 //network
#define s_imp S_un.S_un_w.s_w2 //imp
#define s_impno S_un.S_un_b.s_b4 //imp #
#define s_lh S_un.S_un_b.s_b3 //logical host
}
$linux:{
struct in_addr {
in_addr_t s_addr; //32位
};
}
return:
0:success
-1:error 并将错误写入errno
int listen(int fd, int backlog);
@fd:
sockfd
@backlog:
是在TCP连接中已经申请连接正在握手的套接字(处在未完成连接队列)的数量和已经完成握手处在连接状态的套接字(处在已完成连接队列)的数量之和的最大值。
return:
0:success
-1:error 并将错误写入errno
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
@sockfd:
socket描述符
@addr:
sockaddr 结构体指针,用于返回客户端的协议地址
@addrlen:
socklen_t类型的指针
return :
返回一个描述字表示tcp连接,-1错误
int connect(SOCKET s, const struct sockaddr * name, int namelen);
@s:
socket
@name:
struct sockaddr_in
@namelen:
结构体长度
int recv( SOCKET s, char *buf, int len, int flags);
@s:
待接收数据的套接字
@buf:
为存放数据的缓冲区地址
@len:
为缓冲区长度
@flags:
为特殊操作的标志位,一般写0即可
@return:
数据字节数
int send( SOCKET s,const char* buf,int len,int flags);
@s:
待接收数据的套接字
@buf:
为需要发送的数据的地址
@len:
为发送数据的长度
@flags:
为特殊操作的标志位,一般写0即可
@return:
数据字节数
#include <sys/types.h>
#include <sys/socket.h>
@sockfd:
套接字描述符
@level:
级别
1)SOL_SOCKET:通用套接字选项.
2)IPPROTO_IP:IP选项.
3)IPPROTO_TCP:TCP选项.
@optname:
控制选项名
选项名称 说明 数据类型
========================================================
SOL_SOCKET
-------------------------------------------------------
SO_BROADCAST 允许发送广播数据 int
SO_DEBUG 允许调试 int
SO_DONTROUTE 不查找路由 int
SO_ERROR 获得套接字错误 int
SO_KEEPALIVE 保持连接 int
SO_LINGER 延迟关闭连接 struct linger
SO_OOBINLINE 带外数据放入正常数据流 int
SO_RCVBUF 接收缓冲区大小 int
SO_SNDBUF 发送缓冲区大小 int
SO_RCVLOWAT 接收缓冲区下限 int
SO_SNDLOWAT 发送缓冲区下限 int
SO_RCVTIMEO 接收超时 struct timeval
SO_SNDTIMEO 发送超时 struct timeval
SO_REUSERADDR 允许重用本地地址和端口 int
SO_TYPE 获得套接字类型 int
SO_BSDCOMPAT 与BSD系统兼容 int
=================================================
IPPROTO_IP
----------------------------------------------------------
IP_HDRINCL 在数据包中包含IP首部 int
IP_OPTINOS IP首部选项 int
IP_TOS 服务类型 int
IP_TTL 生存时间 int
===============================================
IPPRO_TCP
---------------------------------------------------------
TCP_MAXSEG TCP最大数据段的大小 int
TCP_NODELAY 不使用Nagle算法 int
================================================
@optval:
设置值的地址
@optlen:
设置值的大小
return:
0:成功
-1:错误,并把错误写入errno
int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
设置SO_RCVBUF 就是设定窗口大小,设定小于1152,窗口仍设定为1152