首页 > 编程语言 >网络编程地址操作函数

网络编程地址操作函数

时间:2024-02-14 15:55:58浏览次数:25  
标签:sockaddr 函数 int 编程 char 地址 指针 struct

网络地址adderss

目录

Berkeley套接字接口拟定了一个通用套接字地址结构sockaddr,用于表示任意类型的地址,所有的套接字API在传入地址参数时都只需要传入sockaddr类型,以保证接口的通用性。除通用地址结构sockaddr外,还有一系列表示具体的网络地址的结构,这些具体的网络地址结构用于用户赋值,但在使用时,都要转化成sockaddr的形式。

sockaddr表示通用套接字地址结构,其定义如下:

struct sockaddr
{
    unsigned short sa_family; // 地址族,也就是地址类型
    char sa_data[14];         // 地址内容
};

所有的套接字API都是以指针形式接收sockaddr参数,并且额外需要一个地址长度参数,这可以保证当sockaddr本身不足以容纳一个具体的地址时,可以通过指针取到全部的内容。比如上面的地址内容占14字节,这并不足以容纳一个128位16字节的IPv6地址。但当以指针形式传入时,完全可以通过指针取到适合IPv6的长度。

struct sockaddr_in
{
    unsigned short sin_family; // 地址族,IPv4的地址族为AF_INET
    unsigned short sin_port;   // 端口
    struct in_addr sin_addr;   // IP地址,IPv4的地址用一个32位整数来表示
    char sin_zero[8];          // 填充位,填零即可
};

typedef uint32_t in_addr_t;
struct in_addr
{
    in_addr_t s_addr;
};
 
struct sockaddr_in6
{
    unsigned short sin6_family; // 地址族,IPv6的地址族为AF_INET6
    in_port_t sin6_port;        // 端口
    uint32_t sin6_flowinfo;     // IPv6流控信息
    struct in6_addr sin6_addr;  // IPv6地址,实际为一个128位的结构体
    uint32_t sin6_scope_id;     // IPv6 scope-id
};
 
struct sockaddr_un
{
    unsigned short sun_family;  // 地址族,Unix域套字地址族为AF_UNIX
    char sun_path[108];         // 路径字符串
};

getsockname getpeername

getsockname 返回与某个套接字关联的本地协议地址
getpeername 返回与某个套接字关联的外地协议地址

int getsockname (int sockfd, struct sockaddr * localaddr, socklen_t addrlen);
int getsockname (int sockfd, struct sockaddr * peerladdr, socklen_t addrlen);

这两个函数都装填由localaddr或peerladdr指针所指的套接字地址结构,协议地址返回到这里
输出 成功为0 , 出错则为-1

gethostbyname

返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针

struct hostent *gethostbyname(const char * hostname);

返回值的结构体:
struct hostent
{
    char FAR * h_name;
    char FAR * FAR * h_aliases;
    short h_addrtype;
    short h_length;
    char FAR * FAR * h_addr_list;
};

h_name成员是我们正在查询的主机的官方名字。也就是主机的权威名字。如果我们提供了一个别名,或是不带域名的主机名,那么这个成员就会描述我们要查询的正确名字
h_aliases成员是我们查询的主机名的别名数组。这个列表的结尾被标记为NULL指针
在成员h_addrtype中返回的值为AF_INET。然而,因为IPv6已经完全实现,名字服务器也会返回IPv6地址。当这种情况发生时,h_addrtype就会在合适的时候返回AF_INET6。
h_addrtype值的上的就是表明在列表h_addr_list中的地址格式
h_length成员这个值与h_addrtype成员相关。对于当前的TCP/IP协议版本(IPv4),这个成员的值总是为4,表明4个字节的IP地址。然而,当IPv6实现时,这个值将会是16,并且返回IPv6地址
h_addr_list成员当执行一个名字到IP地址的转换时,这个成员就会成为我们最重要的信息。当h_addrtype成员包含AF_INET时,这个数组中的每一个指针指向一个4字节的IP地址。这个列表的结尾被标记为NULL指针
返回 :成功时为非空指针,出错则为NULL且设置h_errno

gethostbyaddr

由一个二进制的IP地址找到主机名,与gethostbyname恰好相反

struct hostent *gethostbyaddr(const char * addr , socklen_t len , int family);

len为addr大小,family为协议族
返回 :成功时为非空指针,出错则为NULL且设置h_errno

getservbyname getservbyport

如果我们在代码中通过其名字而不是端口号来指代一个服务,而且从名字到端口号的映射关系保存在一个文件中,那么即使端口号发生变动我们修改那个映射文件即可,而不必重新编译程序
getservbyname用于根据给定名字查找相应的端口
getservbyport用于根据端口号和可选协议查找相应服务

struct servent *getservbyname(const char * servname , const char *protoname);
struct servent *getservbyport(int port , const char *protoname)

返回值的结构体:
struct servent{
    char *s_name; //正式名称
    char **s_aliases; //别名
    int s_port; //端口号
    char *s_proto; //协议
}

servname服务名
port端口号
protoname为可选协议
返回 :成功时为非空指针,出错则为NULL

getaddrinfo

gethostbyname和getservbyname只适用于IPv4
getaddrinfo可以IPv4和IPv6,能够处理名字到地址以及服务到端口这两种转换

int getaddrinfo(const char *hostname, const char *service,const struct addrinfo *hints, struct addrinfo **result);

通过result指针返回一个指向addrinfo结构链表的指针
struct addrinfo {
    int ai_flags;   /* 标志位 */
    int ai_family;    /* 协议族: AF_INET|AF_INET6|AF_UNSPEC... */
    int ai_socktype;    /* sock类型: SOCK_DGRAM|SOCK_STREAM */
    int ai_protocol;    /* 协议类型: IPPROTO_TCP|IPPROTO_UDP... */
    socklen_t ai_addrlen;   /* 地址结构长度 */
    char *ai_canonname; /* host的正式名称 */
    struct sockaddr *ai_addr;   /* 地址结构 */
    struct addrinfo *ai_next;   /* result是个链表结构,ai_next指向下一个addrinfo */
}

ai_flags:
1)AI_ADDRCONFIG: 只有当本地主机被配置为IPv4时,getaddrinfo返回IPv4地址,IPv6同理。
2)AI_CANONNAME: ai_canonname默认为NULL,设置此标志位,告诉getaddrinfo将列表中第一个addrinfo结构体的ai_cannoname字段指向host的权威(官方)名字。
3)AI_NUMERICSERV: service默认为服务名或端口号。这个标志强制参数service为端口号。
4)AI_PASSIVE: getaddrinfo默认返回套接字地址,客户端可以在调用connect时用作主动套接字。此标志位告诉该函数,返回的套接字地址可能被服务器用作监听套接字。此时,host应该为NULL。
5)AI_NUMERICHOST:用于指示getaddrinfo函数在解析主机名时是否进行名称解析。当我们需要使用IP地址而不是主机名来创建套接字时,可以将AI_NUMERICHOST常量作为getaddrinfo函数的hints参数中的ai_flags成员的值,以指示getaddrinfo函数不进行主机名解析,而直接使用传入的IP地址。这样可以避免主机名解析带来的延迟和不确定性,提高套接字的创建效率和可靠性。

hostname:主机名或IP地址字符串(IPv4的点分十进制/IPv6的16进制数串),如果为NULL,则表示本地主机
service:服务名称或端口号字符串,如果为NULL,则返回所有可用的套接字地址结构
hints:用于指定期望的套接字类型、协议及其他选项的addrinfo结构体指针,也可以为空指针
result:用于存储结果的addrinfo结构体指针
成功返回0,出错为非0

freeaddrinfo

释放由getaddrinfo返回的addrinfo结构

void freeaddrinfo(struct addrinfo *ai);

ai应指向第一个addrinfo结构

gai_strerror

由getaddrinfo返回的非0错误值的名字和含义gai_strerror作为它的参数返回一个指向信心串的指针

const char *gai_strerror(int error);

getnameinfo

它是getaddrinfo的互补函数,它以一个套接字地址结构为参数,返回其中的主机的一个字符串和描述其中服务的另一个字符串

int getnamefo(const struct sockaddr *sockaddr, socklen_t addrlen, char *host, socklen_t hostlen,char *serv, socklen_t servlen, int flags); 

成功返回0,出错为非0

host_serv

该函数初始化一个hints结构,可被getaddrinfo调用

struct addrinfo *host_serv(const char *hostname , const char *service , int family , int socktype);

成功返回指向addrinfo结构的指针,出错为NULL

getifaddrs

函数用于获取本机所有网络接口的信息。

#include <sys/types.h>
#include <ifaddrs.h>
​
/*  getifaddrs创建一个链表,链表上的每个节点都是一个struct ifaddrs结构,getifaddrs()返回链表第一个元素的指针。
 *  成功返回0, 失败返回-1,同时errno会被赋允相应错误码。 */
int getifaddrs(struct ifaddrs **ifap);
​
/*  释放ifaddrs */
void freeifaddrs(struct ifaddrs *ifa);
​
struct ifaddrs {
   struct ifaddrs  *ifa_next;    /* 指向链表中下一个struct ifaddr结构 */
   char            *ifa_name;    /* 网络接口名 */
   unsigned int     ifa_flags;   /* 网络接口标志 */
   struct sockaddr *ifa_addr;    /* 指向一个包含网络地址的sockaddr结构 */
   struct sockaddr *ifa_netmask; /* 指向一个包含网络掩码的结构 */
   union {
       struct sockaddr *ifu_broadaddr;
                        /* 如果(ifa_flags&IFF_BROADCAST)有效,ifu_broadaddr指向一个包含广播地址的结构 */
       struct sockaddr *ifu_dstaddr;
                        /* 如果(ifa_flags&IFF_POINTOPOINT)有效,ifu_dstaddr指向一个包含p2p目的地址的结构 */
} ifa_ifu;
#define              ifa_broadaddr ifa_ifu.ifu_broadaddr
#define              ifa_dstaddr   ifa_ifu.ifu_dstaddr
   void            *ifa_data;    /* 指向一个缓冲区,其中包含地址族私有数据。没有私有数据则为NULL */
};

inet_pton

用于将点分十进制形式的IPv4地址或冒号十六进制表示的IPv6地址转换为二进制网络字节顺序的形式

#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);

af:地址家族(address family),可以是 AF_INET(对于IPv4)或 AF_INET6(对于IPv6)。
src:指向包含要转换的IP地址字符串的指针。
dst:指向足够大的缓冲区的指针,用于存储转换后的网络字节顺序格式的IP地址。对于IPv4,通常是一个struct in_addr;对于IPv6,则是一个struct in6_addr。
return: 如果转换成功,返回非零值


标签:sockaddr,函数,int,编程,char,地址,指针,struct
From: https://www.cnblogs.com/radixun/p/18015245

相关文章

  • 实验 2 Scala 编程初级实践
    参考博客——https://www.cnblogs.com/kt-xb/p/12297023.html Linux—— 进入Scala所在目录,创建文件夹mycode 赋予文件夹权限 chmod-R777文件夹所在目录 创建test.scala,输入代码,执行文件代码内容——importscala.io.StdInobjecttest{    defmain(arg......
  • 第五章:面向对象编程
    1.面向对象概述软件开发方法:面向过程和面向对象面向过程:关注点在实现功能的步骤上PO:ProcedureOriented。代表语言:C语言面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。例如开汽车:启动、踩离合、挂挡、松......
  • C++ map自定义比较函数遵守严格弱序
    C++map自定义比较函数遵守严格弱序问题背景及定位背景:这个问题是在将tablesaw(一个Java的数据处理项目)迁移到C++时出现的。问题位置:SplitOn()函数,在数据流水线中的aggregate阶段。问题描述:使用google/benchmark进行了批量化的性能测试,在测试中出现偶发性段错误,几率大约在万分......
  • 农村高中生源转型期提升学生二次函数建模能力的课堂探究
       良好的教学情境是促使学生开展主动思考和深度学习活动的重要保障。数学知识都源于现实生活,所以在培养高中生建模思想与意识期间,除了注意结合数学教材中的相关内容之外,也要注意紧密联系学生的实际生活。因为建模思想的应用都建立在对生活中实际问题的抽象化表达上,所以如果......
  • 【c语言】字符串常见函数 下
    ......
  • 通过解析库探究函数式抽象代价
    前因在春节前了解到Rust语言有一个叫nom的解析库它可以让你创建安全的解析器,而不会占用内存或影响性能。它依靠Rust强大的类型系统和内存安全来生成既正确又高效的解析器,并使用函数,宏和特征来抽象出容易出错的管道。nom核心是解析器组合器,而解析器组合器是高阶函数,可以......
  • c++定义类的时候,只提供拷贝构造函数而不提供默认(无参)构造函数和有参构造函数会怎样?
    4.2.4构造函数调用规则默认情况下,c++编译器至少给一个类添加三个函数:默认构造函数(无参,函数体为空)默认析构函数(无参,函数体为空)默认拷贝构造函数(对属性进行值拷贝)构造函数调用规则:如果用户定义有参构造函数,编译器不会提供默认(无参)构造,但是会提供默认拷贝构造函数如果用户......
  • Go语言精进之路读书笔记第25条——了解变长参数函数的妙用
    25.1什么是变长参数变长参数函数:调用时可以接受零个、一个或多个实际参数的函数。funcPrintln(a...interface{})(nint,errerror)只能有一个“...T”类型形式参数,且该形式参数应该为函数参数列表中的最后一个形式参数。“...T”类型形式参数在函数内呈现为[]T类型的变......
  • pandas.DataFrame.drop()函数
    在Pandas库中,DataFrame.drop()用于移除DataFrame中的行或列。df.drop(labels=None,axis=0,index=None,columns=None,level=None,inplace=False,errors='raise')参数:1.labels:要删除的列或者行,如果要删除多个,传入列表2.axis:轴的方向,0为行,1为列,默认为03.......
  • Go语言精进之路读书笔记第22条——使用defer让函数更简介、更健壮
    22.1defer的运行机制在Go中,只有在函数和方法内部才能使用defer。defer关键字后面只能接函数或方法,这些函数被成为deferred函数。defer将它们注册到其所在goroutine用于存放deferred函数的栈数据结构中。在执行defer的函数退出前,按后进先出(LIFO)的顺序调度执行。22.2defer的......