套接字编程
1 套接字的地址结构:
通用的套接字地址:
struct sockaddr{
unsigned short sa_family; //地址协议,ipv4 TCP/IP:AF_INET,IPV6 :AF_INET6
char sa_data[14]; //14字节的地址协议
};
TCP/IP协议族的地址结构:
struct sockaddr_in{
unsigned short sin_family; //地址类型
unsigned short int sin_port //端口号
struct in_addr sin_addr //ip地址
unsigned char sin_zero[8]; //填充字节,一般赋值未0
}
通常在编写基于TCP/IP协议的网络程序时,使用 结构体sockaddr_in来设置地址,然后通过强制类型转化成sockaddr类型。
2 创建套接字
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
domain用于指定创建套接字所使用的协议组。常用的有:AF_UNIX 创建只在本机内进行通信的套接字,AF_INTE IPv4 , AF_INET6 IPv6
type指定套接字的类型 SOCK_STREAM 创建TCP流套接字 SOCK_DGRAM 创建UDP数据报套接字
protocol 通常设置为0,表示通过参数domain指定的协议族和参数type指定的套接字类型来确定使用的协议。
建立链接
int connect(int sockfd,const struct sockaddr *serv_addr, socklen_t addrlen);
绑定套接字
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
在套接字上监听
int listen(int s, int backlog) //参数backlog指定了已经建立的链接最大长度
接受链接
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);//s是经bind绑定到本地某一端口上的,并有listen转化而来的监听套接字 , 参数addr用来保存发起链接请求的主机的地址和接口 ,addrlen是addr所指向的结构体大小。
TCP套接字的数据传输
发送数据: ssize_t send(int s, const void *msg, size_t len, int flags); //s为已建立好链接的套接字描述符,msg指向存放待发送数据的缓冲区,len为待发送数据的长度,flags为控制长度:一般为MSG_OOB 发送外待数据MSG_DONTROUTE通过最直接的路径发送数据
接收数据: ssize_t recv(int s, void *buf, size_t len, int flags);
UDP套接字的数据传输
发送数据: ssize_t sendto(int s,const void *msg,size_t len,int flags,const struct sockaddr *to,socklen_t tolen); //不需要套接字处于链接状态,所以需要to指定目的地址
接收数据: recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);//from保存数据的源地址
关闭套接字
int close(int fd);
int shutdown(int s,int how);//how指定了关闭的方式:SHUT_RD读通道关闭,但仍可发送数据,SHUT_WR写通道关闭,可接受数据,SHUT_RDWR读写通道都关闭
字节顺序和转换函数
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);//how to network long 将主机unsigned int 型数据转化成网络字节顺序
uint16_t htons(uint16_t hostshort);//how to network short 将主机unsigned short 型数据转换成网络字节顺序
uint32_t ntohl(uint32_t netlong);//和htonl功能相反
uint16_t ntohs(uint16_t netshort);//和htons功能相反
inet 系列函数
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);//将cp所指向的字符串形式的IP地址转换成为二进制的网络字节顺序的IP地址,结果村于inp中
in_addr_t inet_addr(const char *cp);//和inet_aton功能相同,只不过它执行成功后将结果返回
in_addr_t inet_network(const char *cp);//将cp所指的字符串形式的网络地址转换为主机字节顺序形式的二进制IP地址。
char *inet_ntoa(struct in_addr in);//将数值为in的网络字节顺序形式的二进制IP转化成点分十进制字符串形式
struct in_addr inet_makeaddr(int net, int host);//将主机号和网络号组合成一个网络地址
in_addr_t inet_lnaof(struct in_addr in);//从in中提取出主机地址
in_addr_t inet_netof(struct in_addr in);//从in中提取出网络地址