发布时间:2025-12-10 19:33:33 浏览次数:5
Linux【网络库】| 【02 <netdb.h>】以及网络常用结构体文章目录一、简介二、常用结构体1、addrinfo2、sockaddr_storage三、常用函数1、getaddrinfo2、gai_strerror3、freeaddrinfo4、getnameinfo案例stddefsys.unstdintbyteswap一、简介网络数据库操作的定义;二、常用结构体1、addrinfostructaddrinfo{intai_flags; –
stddefsys.unstdintbyteswap 是否还在为Ide开发工具频繁失效而烦恼,来吧关注以下公众号获取最新激活方式。亲测可用!
【正版授权,激活自己账号】:Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】:官方授权 正版激活 自己使用,支持Jetbrains家族下所有IDE…
网络数据库操作的定义;
struct addrinfo { int ai_flags; - AI_NUMERICHOST:标志禁止任何可能冗长的网络主机地址查找 - AI_PASSIVE:返回的套接字地址将包含“通配符地址”(INADDR_ANY用于 IPv4 地址, IN6ADDR_ANY_INIT用于 IPv6 地址; - 未设置 AI_PASSIVE 标志,则返回的套接字地址将适用于connect、 sendto或sendmsg ; int ai_family;// 字段指定返回地址所需的地址族 - AF_INET:ipv4 - AF_INET6:ipv6 - AF_UNSPEC:返回任何可以用于node和service的地址族的套接字地址; int ai_socktype;// 首选套接字类型,可指定0表示任意 int ai_protocol;// 返回套接字的协议,可指定0表示任意 socklen_t ai_addrlen;// addr长度 struct sockaddr *ai_addr;// 结构体 char *ai_canonname; struct addrinfo *ai_next;}; struct sockaddr_storage { sa_family_t ss_family; // 地址族}; #include <sys/socket.h>#include <netdb.h>int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);/*** func:给定节点和服务,它们标识一个Internet主机和一个服务;返回一个或多个addrinfo结构, 每个都包含一个可以指定的 Internet 地址;* @param node:* @param service:* @param hints:* @param res:* return:成功返回0,失败返回errno;errno:EAI_ADDRFAMILY:指定的网络主机在请求的地址族中没有任何网络地址 EAI_AGAIN:稍后再试; EAI_FAIL:永久的故障指示*/ #include <sys/socket.h>#include <netdb.h>void gai_strerror(struct addrinfo *res);/*** func:获取地址和名称信息错误描述;*/ #include <sys/socket.h>#include <netdb.h>void freeaddrinfo(struct addrinfo *ai);/*** func:释放一个或多个由getaddrinfo()返回的addrinfo结构,以及与这些结构相关的任何附加存储;*/ #include <sys/socket.h>#include <netdb.h>int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);/*** func:将套接字地址转换为相应的主机和服务并返回;* @param sa:套接字地址结构,保存输入的IP地址和端口号;* @param salen:sa的长度;* @param host:调用者分配缓冲区;* @param hostlen:host长度;* @param serv:调用者分配缓冲区;* @param servlen:serv长度* @param flags:NI_NAMEREQD:若无法确定主机名,则返回一个错误;NI_DGRAM:基于数据报(UDP)而不是基于流(TCP)的;NI_NOFQDN:只返回本地主机的完全限定域名的主机名部分;NI_NUMERICHOST:返回主机名的数字形式;NI_NUMERICSERV:返回服务地址的数字形式;* return:成功返回0,【节点和服务名称将使用以空字符结尾的字符串填充】;失败设置errno:EAI_AGAIN:无法解析该名称, 稍后再试;EAI_BADFLAGS:flags参数的值无效;EAI_FAIL:不可恢复的错误;EAI_FAMILY:无法识别地址族,或指定地址族的地址长度无效 EAI_MEMORY:溢出; EAI_NONAME:名称不能解析所提供的参数EAI_OVERFLOW:溢出; EAI_SYSTEM:系统错误;*/【注意】:调用者可以通过提供一个NULL host(或serv)参数或一个零hostlen(或servlen)参数来指定不需要主机名(或不需要服务名)。 但是,必须请求至少一个主机名或服务名。 server
/*---------------------------------------------------------------------- > File Name: server.cpp > Author: Jxiepc > Mail: Jxiepc > Created Time: Thu 24 Mar 2022 03:16:00 PM CST ----------------------------------------------------------------------*/#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/socket.h>#include <netdb.h>#define BUF_SIZE 500int main(int argc, char *argv[]){ struct addrinfo hints;struct addrinfo *result, *rp;int sfd, s;struct sockaddr_storage peer_addr;socklen_t peer_addr_len;ssize_t nread;char buf[BUF_SIZE];if (argc != 2) { fprintf(stderr, "Usage: %s port\n", argv[0]);exit(EXIT_FAILURE);}memset(&hints, 0, sizeof(struct addrinfo));hints.ai_family = AF_UNSPEC; /* 允许 IPv4 or IPv6 */hints.ai_socktype = SOCK_DGRAM; /* 数据报 */hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */hints.ai_protocol = 0; /* Any protocol */hints.ai_canonname = NULL;hints.ai_addr = NULL;hints.ai_next = NULL;s = getaddrinfo(NULL, argv[1], &hints, &result);if (s != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));exit(EXIT_FAILURE);}/* 尝试每个地址,直到绑bind 如果socket或bind失败, 我们关闭socket并尝试下一个地址。 . */for (rp = result; rp != NULL; rp = rp->ai_next) { sfd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);if (sfd == -1)continue;if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)break; /* Success */close(sfd);}if (rp == NULL) { /* No address succeeded */fprintf(stderr, "Could not bind\n");exit(EXIT_FAILURE);}freeaddrinfo(result); /* No longer needed *//* 读取数据报并将其回传给发送者 */for (;;) { peer_addr_len = sizeof(struct sockaddr_storage);nread = recvfrom(sfd, buf, BUF_SIZE, 0,(struct sockaddr *) &peer_addr, &peer_addr_len);if (nread == -1)continue; /* Ignore failed request */char host[NI_MAXHOST], service[NI_MAXSERV];s = getnameinfo((struct sockaddr *) &peer_addr,peer_addr_len, host, NI_MAXHOST,service, NI_MAXSERV, NI_NUMERICSERV);if (s == 0)printf("Received %ld bytes from %s:%s\n",(long) nread, host, service);elsefprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));if (sendto(sfd, buf, nread, 0,(struct sockaddr *) &peer_addr,peer_addr_len) != nread)fprintf(stderr, "Error sending response\n");}} client
/*---------------------------------------------------------------------- > File Name: clien.cpp > Author: Jxiepc > Mail: Jxiepc > Created Time: Thu 24 Mar 2022 03:18:56 PM CST ----------------------------------------------------------------------*/#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#define BUF_SIZE 500int main(int argc, char *argv[]){ struct addrinfo hints;struct addrinfo *result, *rp;int sfd, s, j;size_t len;ssize_t nread;char buf[BUF_SIZE];if (argc < 3) { fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);exit(EXIT_FAILURE);}/* 获取匹配主机/端口的地址 */memset(&hints, 0, sizeof(struct addrinfo));hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */hints.ai_flags = 0;hints.ai_protocol = 0; /* Any protocol */s = getaddrinfo(argv[1], argv[2], &hints, &result);if (s != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));exit(EXIT_FAILURE);}/* 返回地址结构的列表。 尝试每个地址,直到我们成功connect 如果socket或connect失败,我们关闭socket并尝试下一个地址 */for (rp = result; rp != NULL; rp = rp->ai_next) { sfd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);if (sfd == -1)continue;if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)break; /* Success */close(sfd);}if (rp == NULL) { /* No address succeeded */fprintf(stderr, "Could not connect\n");exit(EXIT_FAILURE);}freeaddrinfo(result); /* No longer needed *//* 将其余的命令行参数作为单独的数据报发送,并从服务器读取响应 */for (j = 3; j < argc; j++) { len = strlen(argv[j]) + 1;/* +1 for terminating null byte */if (len + 1 > BUF_SIZE) { fprintf(stderr,"Ignoring long message in argument %d\n", j);continue;}if (write(sfd, argv[j], len) != len) { fprintf(stderr, "partial/failed write\n");exit(EXIT_FAILURE);}nread = read(sfd, buf, BUF_SIZE);if (nread == -1) { perror("read");exit(EXIT_FAILURE);}printf("Received %ld bytes: %s\n", (long) nread, buf);}exit(EXIT_SUCCESS);}