netdb(Linux【网络库】- 【02 <netdb.h>】以及网络常用结构体)

发布时间:2025-12-10 19:33:33 浏览次数:5

Linux【网络库】| 【02 <netdb.h>】以及网络常用结构体-NETD标注

Linux【网络库】| 【02 <netdb.h>】以及网络常用结构体文章目录一、简介二、常用结构体1、addrinfo2、sockaddr_storage三、常用函数1、getaddrinfo2、gai_strerror3、freeaddrinfo4、getnameinfo案例stddefsys.unstdintbyteswap一、简介网络数据库操作的定义;二、常用结构体1、addrinfostructaddrinfo{intai_flags; –

文章目录

一、简介 二、常用结构体 1、addrinfo 2、sockaddr_storage 三、常用函数 1、getaddrinfo 2、gai_strerror 3、freeaddrinfo 4、getnameinfo 案例
stddefsys.unstdintbyteswap

是否还在为Ide开发工具频繁失效而烦恼,来吧关注以下公众号获取最新激活方式。亲测可用!

为防止网络爬虫,请关注公众号回复”口令”

激活idea 激活CLion DataGrip DataSpell dotCover dotMemory dotTrace GoLand PhpStorm PyCharm ReSharper ReShaC++ Rider RubyMine WebStorm 全家桶 刷新

【正版授权,激活自己账号】:Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】:官方授权 正版激活 自己使用,支持Jetbrains家族下所有IDE…

一、简介

网络数据库操作的定义;

二、常用结构体

1、addrinfo

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;};

2、sockaddr_storage

struct sockaddr_storage {        sa_family_t  ss_family;     // 地址族};

三、常用函数

1、getaddrinfo

#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:永久的故障指示*/

2、gai_strerror

#include <sys/socket.h>#include <netdb.h>void gai_strerror(struct addrinfo *res);/*** func:获取地址和名称信息错误描述;*/

3、freeaddrinfo

#include <sys/socket.h>#include <netdb.h>void freeaddrinfo(struct addrinfo *ai);/*** func:释放一个或多个由getaddrinfo()返回的addrinfo结构,以及与这些结构相关的任何附加存储;*/

4、getnameinfo

#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);}
需要做网站?需要网络推广?欢迎咨询客户经理 13272073477