getpeername函数与getsockname函数的介绍-程序员宅基地

技术标签: 嵌入式-Linux  linux  嵌入式  

getpeername函数用于获取与某个套接字关联的外地协议地址

getsockname函数用于获取与某个套接字关联的本地协议地址

 

函数定义如下:

#include<sys/socket.h>
 
int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
 
int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);
调用成功,则返回0,如果调用出错,则返回-1

 

 getpeername只有在连接建立以后才调用,否则不能正确获得对方地址和端口,所以它的参数描述字一般是已连接描述字而非监听套接口描述字。
    没有连接的UDP不能调用getpeername,但是可以调用getsockname和TCP一样,它的地址和端口不是在调用socket就指定了,而是在第一次调用sendto函数以后。
    已经连接的UDP,在调用connect以后,这2个函数(getsockname,getpeername)都是可以用的。但是这时意义不大,因为已经连接(connect)的UDP已经知道对方的地址。

  需要这两个函数的理由如下:

  •  在一个没有调用bind的TCP客户上,connect成功返回后,getsockname用于返回由内核赋予该连接的本地IP地址和本地端口号。

  •  在以端口号为0调用bind(告知内核去选择本地临时端口号)后,getsockname用于返回由内核赋予的本地端口号。

  •  在一个以通配IP地址调用bind的TCP服务器上,与某个客户的连接一旦建立(accept成功返回),getsockname就可以用于返回由内核赋予该连接的本地IP地址。在这样的调用中,套接字描述符参数必须是已连接套接字的描述符,而不是监听套接字的描述符。

  •  当一个服务器的是由调用过accept的某个进程通过调用exec执行程序时,它能够获取客户身份的唯一途径便是调用getpeername。

 

手册中介绍

GETPEERNAME(2)                                                                Linux Programmer's Manual                                                                GETPEERNAME(2)

NAME
       getpeername - get name of connected peer socket

SYNOPSIS
       #include <sys/socket.h>

       int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

DESCRIPTION
       getpeername()  returns  the  address of the peer connected to the socket sockfd, in the buffer pointed to by addr.  The addrlen argument should be initialized to indicate the
       amount of space pointed to by addr.  On return it contains the actual size of the name returned (in bytes).  The name is truncated if the buffer provided is too small.

       The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.

RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

ERRORS
       EBADF  The argument sockfd is not a valid descriptor.

       EFAULT The addr argument points to memory not in a valid part of the process address space.

       EINVAL addrlen is invalid (e.g., is negative).

       ENOBUFS
              Insufficient resources were available in the system to perform the operation.

       ENOTCONN
              The socket is not connected.

       ENOTSOCK
              The file descriptor sockfd does not refer to a socket.

CONFORMING TO
       POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (getpeername() first appeared in 4.2BSD).

NOTES
       The third argument of getpeername() is in reality an int * (and this is what 4.x BSD and libc4 and libc5 have).  Some POSIX confusion resulted in the present socklen_t,  also
       used by glibc.  See also accept(2).

       For  stream sockets, once a connect(2) has been performed, either socket can call getpeername() to obtain the address of the peer socket.  On the other hand, datagram sockets
       are connectionless.  Calling connect(2) on a datagram socket merely sets the peer address for outgoing datagrams sent with write(2) or recv(2).  The caller of connect(2)  can
       use  getpeername()  to  obtain the peer address that it earlier set for the socket.  However, the peer socket is unaware of this information, and calling getpeername() on the
       peer socket will return no useful information (unless a connect(2) call was also executed on the peer).  Note also that the receiver of a datagram can obtain the  address  of
       the sender when using recvfrom(2).

SEE ALSO
       accept(2), bind(2), getsockname(2), ip(7), socket(7), unix(7)

COLOPHON
       This page is part of release 4.04 of the Linux man-pages project.  A description of the project, information about reporting bugs, and the latest version of this page, can be
       found at http://www.kernel.org/doc/man-pages/.

Linux                                                                                 2015-12-28                                                                       GETPEERNAME(2)
GETSOCKNAME(2)                                                                Linux Programmer's Manual                                                                GETSOCKNAME(2)

NAME
       getsockname - get socket name

SYNOPSIS
       #include <sys/socket.h>

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

DESCRIPTION
       getsockname()  returns  the current address to which the socket sockfd is bound, in the buffer pointed to by addr.  The addrlen argument should be initialized to indicate the
       amount of space (in bytes) pointed to by addr.  On return it contains the actual size of the socket address.

       The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.

RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

ERRORS
       EBADF  The argument sockfd is not a valid descriptor.

       EFAULT The addr argument points to memory not in a valid part of the process address space.

       EINVAL addrlen is invalid (e.g., is negative).

       ENOBUFS
              Insufficient resources were available in the system to perform the operation.

       ENOTSOCK
              The file descriptor sockfd does not refer to a socket.

CONFORMING TO
       POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (getsockname() first appeared in 4.2BSD).

NOTES
       The third argument of getsockname() is in reality an int * (and this is what 4.x BSD and libc4 and libc5 have).  Some POSIX confusion resulted in the present socklen_t,  also
       used by glibc.  See also accept(2).

SEE ALSO
       bind(2), socket(2), getifaddrs(3), ip(7), socket(7), unix(7)

COLOPHON
       This page is part of release 4.04 of the Linux man-pages project.  A description of the project, information about reporting bugs, and the latest version of this page, can be
       found at http://www.kernel.org/doc/man-pages/.

Linux                                                                                 2015-12-28                                                                       GETSOCKNAME(2)

我们可以通过套接字描述符来获取自己的IP地址和连接对端的IP地址

服务器代码:

/*服务器端*/
#define MAXLINE 4096
#define PORT 6563
#define LISTENQ 1024
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
 
int main() {
    int listenfd, connfd;
    struct sockaddr_in servaddr;//服务器绑定的地址
    struct sockaddr_in listendAddr, connectedAddr, peerAddr;//分别表示监听的地址,连接的本地地址,连接的对端地址
    int listendAddrLen, connectedAddrLen, peerLen;
    char ipAddr[INET_ADDRSTRLEN];//保存点分十进制的地址
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&servaddr, 0, sizeof(servaddr));
 
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);
    
    bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));//服务器端绑定地址
 
    listen(listenfd, LISTENQ);
    listendAddrLen = sizeof(listendAddr);
    getsockname(listenfd, (struct sockaddr *)&listendAddr, &listendAddrLen);//获取监听的地址和端口
    printf("listen address = %s:%d\n", inet_ntoa(listendAddr.sin_addr), ntohs(listendAddr.sin_port));
 
    while(1) {
        connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);
        connectedAddrLen = sizeof(connectedAddr);
        getsockname(connfd, (struct sockaddr *)&connectedAddr, &connectedAddrLen);//获取connfd表示的连接上的本地地址
        printf("connected server address = %s:%d\n", inet_ntoa(connectedAddr.sin_addr), ntohs(connectedAddr.sin_port));
        getpeername(connfd, (struct sockaddr *)&peerAddr, &peerLen); //获取connfd表示的连接上的对端地址
        printf("connected peer address = %s:%d\n", inet_ntop(AF_INET, &peerAddr.sin_addr, ipAddr, sizeof(ipAddr)), ntohs(peerAddr.sin_port));
    }
    return 0;
}

客户端代码:

/*客户端*/
#define PORT 6563
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
 
int main(int argc, char **argv) {
    struct sockaddr_in servaddr;//服务器端地址
    struct sockaddr_in clientAddr;//客户端地址
    int sockfd; 
    int clientAddrLen = sizeof(clientAddr);
    char ipAddress[INET_ADDRSTRLEN];//保存点分十进制的ip地址
    
    if(argc < 2) {
        printf("parameter error");
    }
 
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);  
    if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
        printf("server address error\n");//地址参数不合法
    }
 
    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));//向服务器端发起连接请求
    
    getsockname(sockfd, (struct sockaddr*)&clientAddr, &clientAddrLen);//获取sockfd表示的连接上的本地地址
 
    printf("client:client ddress = %s:%d\n", inet_ntop(AF_INET, &clientAddr.sin_addr, ipAddress, sizeof(ipAddress)), ntohs(clientAddr.sin_port));
    return 0;
}

 

 

 

 

 

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/andrewgithub/article/details/81812458

智能推荐

linux c 实现简易HTTP服务器_linux c http-程序员宅基地

文章浏览阅读8.6k次,点赞4次,收藏39次。需要用到的知识点:HTTP协议socket通信linux多线程server.c#include #include #include #include #include #include #include #incl_linux c http

服务器装系统进pe界面就死机了,进入PE后安装系统老是会卡住。是什么问题啊。...-程序员宅基地

文章浏览阅读8.7k次。满意答案WJC1986118WJ推荐于 2017.11.27【◆】【你好】【◆】.进入PE后安装系统老是会卡住.建议你重新下载原版镜像,格式化C盘,进行干净安装..还卡则需检测硬盘有无错误及坏道~可使用DiskGenius>检测和尝试修复硬盘坏道..★重要提示:修复硬盘坏磁道,会破坏坏磁道及其临近扇区的数据。请在硬盘坏道修复前,先做好数据备份,以减少不必要的数据损失!!!..★电脑安装(重装..._pe很卡

ffmpeg音视频处理流程核心技术_视频效果演示系统的核心技术-程序员宅基地

文章浏览阅读712次。视频播放器原理 什么是ffmpeg? ffmpeg 音视频编/解码 流程图 ffmpeg 常用 struct AVFormatContext AVStream AVCodecContext AVCodec AVPacket AVFrame ffmpeg 常用Api av_register_all() avformat_alloc_output_context2() avio_open()..._视频效果演示系统的核心技术

Java List集合多种情况处理方法_java list reduce-程序员宅基地

文章浏览阅读449次。Java List集合多种情况处理方法:List集合交集、并集、差集、去重、与数组互转、删除、排序等操作_java list reduce

【UML】软件需求说明书_uml需求文档访客管家-程序员宅基地

文章浏览阅读2.3k次,点赞77次,收藏80次。需求:指人对客观事务需要的表现,体现为愿望、意向和兴趣,因而成为行动的一种直接原因。软件需求(IEEE软件工程标准词汇表):(1)用户解决问题或达到目标所需的条件或能力。(2)系统或系统部件要满足合同、标准、规范或者其他正式规定文档所需具有条 件或能力。(3)对(1)或(2)中的一个条件或一种能力的一种文档化表述。用例:定义 1 用例是对一个活动者使用一个系统的一项功能时进行交互过程中的一个文字描述序列。_uml需求文档访客管家

linux笔记-根文件系统及文件管理命令详解_根文件系统文本登陆-程序员宅基地

文章浏览阅读574次。第三章、Linux根文件系统及文件管理命令详解02_03_Linux根文件系统详解文件系统:rootfs: 根文件系统 FHS:Filesystem Hierarchy Standard(文件系统目录标准)的缩写,多数Linux版本采用这种文件组织形式,类似于Windows操作系统中c盘的文件目录,FHS采用树形结构组织文件。FHS定_根文件系统文本登陆

随便推点

说说内核与计算机硬件结构-程序员宅基地

文章浏览阅读502次。1.内核诸如51/ARM/90/PIC/AVR.....有好多种的,何况内核从来不分类,因为每一家常都可以改内核,你应该问的是架构!!只有懂架构才能用什么片子都驾轻就熟. 我详细的说一下吧. HARVARD(哈佛)架构:ROM(程序空间)与RAM(数据空间)分开,便于程序与数据的同时访问,减少程序运行时访问的瓶颈,提高数据吞吐. PRINCETON(普林斯顿)架构:采用通用计算机广泛使用的..._dcache和微处理器的接口 整个系统的层次结构如图1所示

数据结构应用案例——栈结构用于8皇后问题的回溯求解-程序员宅基地

文章浏览阅读862次。【说明】本文来自由周世平老师主编的《C语言程序设计》教材。我作为参编人员执笔了第7、8章。“第8章 问题求解与算法”中“8.6.1 回溯法”以8皇后问题的求解为例,介绍了回溯法的解题过程。这个解决方案中用到了“栈”,引用至此,作为栈应用的例子。需要说明的是,教材面向程序设计初学者,并全文中并未提出过任何关于“栈”的描述。这样做,隐藏了术..._八皇后栈回溯代码实现数据结构

c语言scanf中的分隔符的作用,C语言中scanf与分隔符(空格回车Tab)-程序员宅基地

文章浏览阅读2.5k次,点赞3次,收藏12次。众所周知,C语言中的scanf函数的作用是从标准输入设备(通常是键盘)读取输入值,并存储到参数列表中指针所指向的内存单元。下面从几个方面说一下一些稍微细节的东西。下面的实验都在vc6.0中通过。1、scanf的返回值scanf通常返回的是成功赋值(从标准输入设备赋值到参数列表所指定的内存区域)的数据项数,如果出错或是遇到end of file(注意,如果想从键盘输入EOF,在windows的DOS..._不同类型输入要分隔符吗c语言

Canvas实现黑客帝国字符雨_canvas画字符雨-程序员宅基地

文章浏览阅读1k次。 利用Canvas的fillText(),隔一定时间在画布上作画&lt;!DOCTYPE html&gt;&lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;meta name="viewport" content="width=device-width,initial-scale=1.0"&gt; &_canvas画字符雨

微信公众号跳转微信小程序,自定义微信跳转标签_opentaglist-程序员宅基地

文章浏览阅读1.1k次。微信公众号跳转微信小程序,自定义微信跳转标签_opentaglist

数据恢复技术与LVM数据恢复方法_vgreduce --removemissing恢复-程序员宅基地

文章浏览阅读4.3k次。数据恢复技术与LVM数据恢复方法 1摘要 随着计算机网络应用的发展,数据存储的安全性变的越来越重要。在常见的基于RAID和LVM的环境下面,当出现硬盘故障或者错误操作导致数据丢失的情况下,采用适当的数据恢复策略可以在很大程度上提供数据恢复的成功概率。本文研究了几种情况下的数据恢复技术和方法,为数据恢复和数据安全的预防提供了指导。 2数据恢复需求 2.1Linux IO存储栈 图(1)Linux IO 存储..._vgreduce --removemissing恢复

推荐文章

热门文章

相关标签