函数文档3
函数文档三
IP 地址结构
struct in_addr{
uint32_t s_addr;
}
IP地址和点分十进制结构
客户端主机和服务端主机的表示方式可能大大的不相同, 一个可能采用的是小端法,另外一个采用的可能是大端法,所以可以根据自己的结构调整顺序。
# include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint32_t htons(uint16_t hostshort);
返回值:按照网络字节顺序
# include <arpa/inet.h>
uint32_t ntonl(uint32_t hostlong);
uint32_t ntons(uint16_t hostshort);
返回值:按照主机字节顺序
套接字结构
/*IP 套接字i地址结构*/
struct sockaddr_in{
uint16_t sin_family; /*使用的协议类型 AF_INET*/
uint16_t sin_port;
struct in_addr sin_addr; /*ip地址*/
unsigned char sin_zero[8];
};
/*通用的套接字地址结构*/
struct sockaddr {
uni16_t sa_family;
char sa_data[4];
}
socket 函数
客户端和服务器使用socket函数创建一个套接字描述符
# include <sys/types.h>
# include <sys/socket.h>
int socket(int domain, int type, int protocol);
让套接字称为链接的一个端点
int clientfd = socket(AF_INET, SOCK_STREAM, 0);
AF_INET 32 位地址
SOCK_STREAM 表示套接字连接的一个端点
通常使用getaddrinfo 自动生成相关的参数
connect函数
include <sys/socket.h>
int connet(int clientfd, const struct sockaddr *addr, socklen_t addlen); addrlen = sizeof(sockaddr_in)
connect会造成阻塞,得到的连接是由套接字对
(x:y, addr.sin_addr:addr.sin_port)
描述
服务器用来和客户端建立连接的函数
bind函数
# include <sys/socket.h>
int bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
b1ind函数服务器套接字地址和sockfd联系起来,和addr中的套接字地址联系起来
listen函数
# include <sys/socket.h>
int listen(int sockfd,int backlog);
listen函数将socket函数创建的主动套接字变成一个监听套接字,这个套接字可以接收来自客户端的连接请求,backlog暗示内核在拒绝链接请求时,队列中排队的请求数量,通常设置为一个很大的值。
accept 函数
#include <sys/socket.h>
int accept(int listenfd, struct sockaddr *addr,int addlen);
listenfd 由listen函数提供,addr是客户端的套接字地址,返回一个已连接描述符。
已连接描述符每次客户端连接请求的时候都会被创建一次,存在于一个客户端服务中。
监听描述符存在于服务器整个生命周期。
监听描述符可以帮助服务器进行并发编程,如果每有一个新的连接请求到达监听描述符可以fork一个新的进程。
getaddinfo函数
将主机名 主机地址 服务名和端口号的字符串转化成套接字结构
# include <sys/types.h>
# include <sys/socket.h>
# include <netdb.h>
int getaddrinfo(const char *host, consta char *service, const struct addrinfo *hints, struct addrinfo **result);
host 参数可以是域名也可以是数字地址(如点分十进制IP地址)
service函数可以是服务名(http),或者是实际你只端口号
result 指的是一个addrinfo结构的链表
void freeaddrinfo(struct addrinfo *result);
//将getaddrinfo中的错误信息转换为消息字符串
const char *gai_strerror(int errcode);
客户端调用getaddrinfo之后 会遍历result 链表,指导socket和connect成功,最后需要释放这个链表避免内存泄露
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
socklen_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
-
ai_socktype 表示
连接
和数据报
,ai_socktype = SOCK_STREAM 将列表限制为每一个地址组多一个的addrinfo结构 结构的套接字地址可以作文连接的一个端点。 -
ai_flag
- AI_ADDRCONFIG
如果在使用
连接
使用这个标志,当本地主机被配置IPV4的时,getaddrinfo
就回返回这个地址 - AI_CANNONNAME 将列表中的第一个addinfo结构的ai_canonname指向host的权威名字
- AI_NUMBERICSERV
参数
service
可以为服务名或者段括号,这个标志强制参数为端口号 - AI_PASSIVE getaddrinfo会返回套接字地址,客户端可以在调用connect的时候这个套接字地址作为主动套接字。这个参数可以让套接字地址为监听套接字。这时,host应该为NULL得到的套接字地址结构的字段是通配符地址,告诉内核服务器会接受发送到该主机的所有IP地址的请求
- AI_ADDRCONFIG
如果在使用
getnameinfo
# include <sys/socket.h>
# include <netdb.h>
int getnameinfo
(const struct sockaddr *sa,socklen_t salen,
char *host, size_t hostlen,
char *service, size_t servlen, int flags);
//如果成功则为0,如果错误则为非零的错误代码
sa 指向salen字节地套接字地址,host指向大小为hostlen的缓冲区。
getnameinfo将套接字地址结构转换成对应的主机和服务名字符串。
上述两个程序都可以使用gai_strerro
转换成字符串
同样也有flags
代码
- NI_NUMBERICHOSTf
getnameinfo
默认返回host中的域名,改变之后返回一个数字字符串。 - NI_NUMBERICSERV 会返回服务名而不是端口号,这样的话会直接返回端口号
套接字接口的辅助函数
# include "csapp.h"
int open_clientfd(char *hostname, char *post);
运行在hostname上 并且在port 监听请求。返回一个套接字描述符。
# include "csapp.h"
int open_listenfd(char *post);