这节本来打算先给出常用函数介绍,再给两个代码实例,写着写着发现越来越长,决定把代码放在下一节。
本节内容持续更新......
1 socket()函数
原型:
int socket(int domain, int type, int protocol);
描述:
类似打开一个文件,返回一个socket描述符,唯一标识一个socket,后面相应的操作都是这用这个socket描述符。
参数:
domain:协议族,常用的协议族有AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE等;
协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定列要使用ipv4与16位端口号组合;
AF_LOCAL决定了要用一个绝对路径名作为地址。
type:socket类型,常用的socket类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET等;
socket类型决定列要使用的传输协议,如SOCK_STREAM对应TCP,SOCK_DGRAM对应UDP.
protocol:协议,常用的有:IPPROTO_TCP、IPPTOTO_UDP、IPPTOTO_SCTP等;
他们分别对应TCP传输协议、UDP传输协议、SCTP传输协议。
返回值:
成功返回一个socket描述符,失败返回-1。
2 bind()函数
原型:
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
描述:
将socket绑定到一个地址,包括IP和端口号。
参数:
sockfd:通过socket返回的一个唯一的描述符;
addr:要绑定给sockfd的地址,是一个结构体指针,这个结构体地址根据socket的地址族不同而不同,ipv4对应的是:
struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET */ in_port_t sin_port; /* port in network byte order */ struct in_addr sin_addr; /* internet address */ }; /* Internet address. */ struct in_addr { uint32_t s_addr; /* address in network byte order */ };addrlen:对应地址的长度,通过sizeof获得
返回值:
成功返回0,失败返回-1。
3 listen()函数
原型:
int listen(int sockfd, int backlog);
描述:
让socket处于监听状态
参数:
sockfd:要设置为监听状态的socket描述符
backlog:可以排队的最大链接个数
返回值:
成功返回0,失败返回-1。
4 accept()函数
原型:
int accept(int sockfd, struct sockaddr* addr, socklen_t *addrlen);
描述:
接收请求
参数:
sockfd:服务器的监听socket描述符
addr:请求链接方的地址
addrlen:地址长度
返回值:
成功返回一个新的socket描述符,失败返回-1。
5 收发消息相应函数
read()/write(); recv()/send(); readv()/writev(); recvmsg()/sendmsg();/* 推荐 */ recvfrom()/sendto();
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); #include <sys/types.h> #include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
read相应函数可以从socket描述符中读取内容
write相应函数可以把内容写道socket描述符中
参数类型:
sockfd:socket描述符
buf/msg:数据流
len/count:数据长度
flags:调用执行方式,一般设为0
dest_addr:目标地址
src_addr:源地址
返回值:
read相应函数成功时返回实际所读到的字节数,结束返回0,错误返回小于0的数。
write相应函数成功时返回实际所写的字节数,失败返回-1。
6 close函数
原型:
int close(int fd);
关闭socket
参数:
fd:要关闭的socketfd或者文件fd
返回值:
成功返回0,失败返回-1
7 perror
原型:
void perror(const char *s);
将上一个函数发生错误的原因输出到stderr,参数s先打印出来,后面加上错误原因字符串,错误字符串依据全局变量errno的值决定的。
在库函数中有个errno变量,每个值对应着以字符串表示的错误原因。当调用某些函数出错时,函数就会重置errno的值。
参数:
错误信息之前的字符串。
8 字节序转换函数
首先有两个概念:
NBO:Network Byte Order 网络字节序,从高到底的顺序从存储(大端优先)。
HBO:Host Byte Order 主机字节序,不同的CPU不同,因此需要转换成NBO。
#include <netinet/in.h> uint16_t htons(uint16_t host16bitvalue);/*host to network Short init*/ uint32_t htonl(uint32_t host32bitvalue);/* host to network long init */ uint16_t ntohs(uint16_t net16bitvalue);/*network to host Short init*/ uint32_t ntohl(uint32_t net32bitvalue); /*network to host long init*/
9 地址转换函数
#include <arpa/inet.h> int inet_aton(const char *strptr, struct in_addr *addrptr);/*参数1:<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">字符串IP;参数2:地址结构体中的sin_addr;</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">返回:1——字符串IP有效,0——</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">字符串IP</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">有错*/</span> char* inet_ntoa(struct in_addr inaddr); /*将一个点分IP转换成字符串*/ in_addr_t inet_addr(const char *strptr);/*将字符串IP转换成网络字节序的IPV4地址*/
#include <netinet/in.h> #define INET_ADDRSTRLEN 16 #define INET6_ADDRSTRLEN 46 #include <arpa/inet.h> int inet_pton(int family, const char *strptr, void *addrptr);/*返回:1——成功,输入的不是有效表达格式,-1——出错*/ const char* inet_ntop(int family, const void *addrptr, char *strptr, size_t len); /*返回:指向结果的指针——成功,NULL——出错*/
10 setsockopt
原型:
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
描述:
在做服务器端开发的时候,经常会遇到这样的问题:程序第一次能启动,后来就一直报错——端口被占用,导致程序起不了。原因是在程序绑定的端口在前一次程序退出之后并没有被释放,这就需要使用这个函数来设置socket状态。
参数:
sockfd:socket描述符
level:定义层次,支持SOL_SOCKET(通用套接字)、IPPROTO_TCP(TCP套接字)、IPPROTO_IP(IPV4)和IPPROTO_IPV6((IPV6)
optname:选择名称
optval:选项值,是一个指向变量的指针类型:整形,套接字结构体,其他类型linger{},timeval{}
optlen:选项长度
返回值:
成功返回0,失败返回-1。
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 服务类型
IP_TTL 生存时间 int
========================================================================
IPPRO_TCP
------------------------------------------------------------------------
TCP_MAXSEG TCP最大数据段的大小 int
TCP_NODELAY 不使用Nagle算法 int
========================================================================
#对应一个函数:int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
持续更新....................