套接字之 getsockname && getpeername

getsockname-获取本地地址;比如,在绑定的时候设置端口号为0由系统自动选择端口绑定,或者使用了INADDR_ANY通配所有地址的情况下,后面需要用到具体的地址和端口,就可以用getsockname获取地址信息;

getpeername-获取建立连接的对端的地址和端口;

下面为源码分析:

 1 /*
 2  *    Get the local address (‘name‘) of a socket object. Move the obtained
 3  *    name to user space.
 4  */
 5
 6 SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
 7         int __user *, usockaddr_len)
 8 {
 9     struct socket *sock;
10     struct sockaddr_storage address;
11     int len, err, fput_needed;
12
13     /* 查找socket */
14     sock = sockfd_lookup_light(fd, &err, &fput_needed);
15     if (!sock)
16         goto out;
17
18     err = security_socket_getsockname(sock);
19     if (err)
20         goto out_put;
21
22     /* 调用socket操作的getname函数 */
23     err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
24     if (err)
25         goto out_put;
26
27     /* 拷贝地址到用户空间 */
28     err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
29
30 out_put:
31     fput_light(sock->file, fput_needed);
32 out:
33     return err;
34 }
 1 /*
 2  *    Get the remote address (‘name‘) of a socket object. Move the obtained
 3  *    name to user space.
 4  */
 5
 6 SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
 7         int __user *, usockaddr_len)
 8 {
 9     struct socket *sock;
10     struct sockaddr_storage address;
11     int len, err, fput_needed;
12
13     /* 查找socket */
14     sock = sockfd_lookup_light(fd, &err, &fput_needed);
15     if (sock != NULL) {
16         err = security_socket_getpeername(sock);
17         if (err) {
18             fput_light(sock->file, fput_needed);
19             return err;
20         }
21
22         /* 调用socket操作的getname获取对端地址,此时最后一个参数为1 */
23         err =
24             sock->ops->getname(sock, (struct sockaddr *)&address, &len,
25                        1);
26
27         /* 将地址拷贝到用户空间 */
28         if (!err)
29             err = move_addr_to_user(&address, len, usockaddr,
30                         usockaddr_len);
31         fput_light(sock->file, fput_needed);
32     }
33     return err;
34 }

ipv4情况下,getsockname和getpeername都会调用下面的inet_getname函数;

 1 /*
 2  *    This does both peername and sockname.
 3  */
 4 int inet_getname(struct socket *sock, struct sockaddr *uaddr,
 5             int *uaddr_len, int peer)
 6 {
 7     struct sock *sk        = sock->sk;
 8     struct inet_sock *inet    = inet_sk(sk);
 9     DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr);
10
11     /* 设置地址族 */
12     sin->sin_family = AF_INET;
13
14     /* 获取对端地址 */
15     if (peer) {
16         /* 目的端口为空或者为未连接状态 */
17         if (!inet->inet_dport ||
18             (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) &&
19              peer == 1))
20             return -ENOTCONN;
21         /* 设置目的端口和地址 */
22         sin->sin_port = inet->inet_dport;
23         sin->sin_addr.s_addr = inet->inet_daddr;
24     }
25     /* 获取本地地址 */
26     else {
27         /* 获取接收时ip */
28         __be32 addr = inet->inet_rcv_saddr;
29
30         /* 不存在则获取发送时ip */
31         if (!addr)
32             addr = inet->inet_saddr;
33
34         /* 设置端口和地址 */
35         sin->sin_port = inet->inet_sport;
36         sin->sin_addr.s_addr = addr;
37     }
38
39     /* 填充部分 */
40     memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
41
42     /* 设置地址长度 */
43     *uaddr_len = sizeof(*sin);
44     return 0;
45 }

原文地址:https://www.cnblogs.com/wanpengcoder/p/11749369.html

时间: 2024-10-16 00:22:02

套接字之 getsockname && getpeername的相关文章

Unix网络编程学习笔记之第4章 基于TCP套接字编程

1. socket函数 int socket(int family, int type,int protocol) 成返回一个套接字描述符.错误返回-1 其中family指定协议族,一般IPv4为AF_INET, IPv6为AF_INET6. 其中type指定套接字类型,字节流:SOCK_STREAM.   数据报:SOCK_DGRAM. 一般情况下通过family和type的组合都可以唯一确定一个套接字类型.所以一般我们就把protocol设为0就可以了. 有时在某些特殊情况下,family和

套接字对象

S 代表一个套接字 s.family : 获取套接字地址族类型 s.type: 获取套接字类型 s.getsockname: 获取套接字的绑定地址和端口 s.fileno : 获取套接字的文件描述符 每一个IO事件操作系统都会分配一个不同的正整数作为编号,该正整数即为这个IO的文件描述符 sys.stdin.fileno() --> 0 [文件描述符] sys.stdout.fileno() -->1 sys.stderr.fileno() -->2 s.getpeername() :

网络套接字与寻址

1 套接字描述 套接字是通信端点的抽象,创建一个套接字使用如下函数: #include <sys/socket.h> int socket(int domain, int type, int protocol); 返回值:若成功,返回套接字描述符:若出错,返回-1. 参数: domain: 指定通信的特征,包括地址格式,以AF_开头的常数表示地址族(address family): 域 描述 AF_INET IPv4因特网域 AF_INET6 IPv6因特网域 AF_UNIX UNIX域 AF

第16章 网络IPC:套接字总结

1 套接字是通信端点的抽象 创建套接字: int socket(int domain,int type,int protocol) domain:通信域 AF_INET.AF_INET6.AF_LOCAL.AF_UNSPEC type:套接字类型,SOCK_DGRAM.SOCK_STREAM.SOCK_SEQPACKET.SOCK_RAW protocol:通常为0,表示domain和type默认的协议 linux中套接字使用文件描述符实现的,文件描述符上使用的大多数函数可以用于套接字 套接字输

socket套接字编程

socket套接字编程 客户端/服务器架构 1.硬件C/S架构(打印机) 2.软件C/S架构 互联网中处处是C/S架构 如黄色网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种) 腾讯作为服务端为你提供视频,你得下个腾讯视频客户端才能看它的视频) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发         详见网络通信原理   socket是什么 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Soc

第九篇:获取套接字相关联信息

前言 知道套接字描述符,如何获取这个套接字连接的相关信息呢?显然,这是一个必须要清楚的问题. 获取本地协议信息 函数原型:int getsockname ( int sockfd, struct sockaddr *localaddr, socklen_t *addrlen ) 函数功能:将本地套接字描述符sockfd对应的连接信息存放进localaddr.若成功返回0,否则返回-1. 包含头文件:sys/socket.h 获取外地协议信息 函数原型:int getpeername ( int

apue学习笔记(第十六章 网络IPC:套接字)

本章将考察不同计算机(通过网络连接)上的进程相互通信的机制:网络进程间通信. 套接字描述符 正如使用文件描述符访问文件,应用程序用套接字描述符访问套接字. 许多处理文件描述符函数(如read和write)可以用于处理套接字描述符.调用socket函数创建一个套接字 #include <sys/socket.h> int socket(int domain,int type,int protocol); 参数domain(域)确定通信的特性,包括地址格式.下图总结了POSIX.1指定的各个域,每

网络编程--Socket(套接字)

网络编程 网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯.网络编程中 有两个主要的问题,一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后 如何可靠高效的进行数据传输.在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的 路由,由IP地址可以唯一地确定Internet上的一台主机.而TCP层则提供面向应用的可靠的 或非可靠的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据 的. 目前较为流行的网络编程模型是客户机/服务器(C/S)结构

[python] 网络编程之套接字Socket、TCP和UDP通信实例

很早以前研究过C#和C++的网络通信,参考我的文章: C#网络编程之Tcp实现客户端和服务器聊天 C#网络编程之套接字编程基础知识 C#网络编程之使用Socket类Send.Receive方法的同步通讯 Python网络编程也类似.同时最近找工作笔试面试考察Socket套接字.TCP\UDP区别比较多,所以这篇文章主要精简了<Python核心编程(第二版)>第16章内容.内容包括:服务器和客户端架构.套接字Socket.TCP\UDP通信实例和常见笔试考题. 最后希望文章对你有所帮助,如果有不