【Linux C | 网络编程】getsockname 和 getpeername函数详解及C语言例子

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍getsockname 和 getpeername函数详解及C语言例子 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭

本文未经允许,不得转发!!!

目录

  • 🎄一、概述
  • 🎄二、getsockname 函数
    • ✨2.1 getsockname 函数介绍
    • ✨2.2 getsockname 函数例子
  • 🎄三、getpeername 函数
    • ✨3.1 getpeername 函数介绍
    • ✨3.2 getpeername 函数例子
  • 🎄四、总结


在这里插入图片描述

🎄一、概述

在网络编程中,套接字句柄fd是很常见的,但有时我们又想要知道该套接字的IP地址和端口号是什么?这时就可以用到本文即将介绍的两个函数,getsockname 和 getpeername:

  • getsockname:可以通过套接字解析出其关联的本端的IP地址、端口、协议;
  • getpeername:可以通过套接字解析出其关联的远端的IP地址、端口、协议;

在这里插入图片描述

🎄二、getsockname 函数

✨2.1 getsockname 函数介绍

getsockname 函数原型:

#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

getsockname 函数在addr指向的缓冲区中返回套接字sockfd绑定到的当前地址。
参数:

  • sockfd:传入参数,要获取IP地址、端口信息的套接字sockfd;
  • addr:传出参数,用来存放获取结果的内存地址;
  • addrlen:传入传出参数,调用是指明第二个参数 addr 指向内存的大小。返回时,它包含套接字地址的实际大小。

返回值:成功返回0,出错返回 -1。

使用场景:
1、在TCP客户端调用 connect 成功返回后,可以获取内核赋予该连接的本地IP和端口号;
2、在以端口号0调用bind(告知内核去选择本地端口号)后,getsockname用于返回由内核赋予的本地端口号。
3、getsockname可用于获取某个套接字的地址族。
4、在一个以通配IP地址调用bind的TCP服务器上,与某个客户的连接一旦建立(accept成功返回),getsockname就可以用于返回由内核赋予该连接的本地IP地址。


✨2.2 getsockname 函数例子

这是一个TCP客户端,需要连接到本地端口为10086的服务端才可以使用,如果没有服务端的话,可以使用下一小节的getsockname 函数例子做服务端。可以参考第4小节。

// getsockname_sample.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>int main()
{// 1、创建TCP套接字socketint sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd<0)perror("socket error" );// 2、准备服务端ip和端口struct sockaddr_in servaddr;bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons (10086);if (inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0) // 设置本机IP为服务端IPperror("inet_pton error");// 3、连接 connectif (connect(sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){perror("connect error" );close(sockfd);return -1;}// connect成功返回后,获取该连接本地套接字IP、端口struct sockaddr_in addr;int addrLen = sizeof(addr);if(0 == getsockname(sockfd, (struct sockaddr*)&addr, &addrLen) )printf("getsockname: ip=[%s], port=%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));// 阻塞等待,可以查看连接信息,使用命令`netstat -at | greep 10086`while(1)sleep(1); // 5、关闭close(sockfd);return 0;
}

在这里插入图片描述

🎄三、getpeername 函数

✨3.1 getpeername 函数介绍

getpeername 函数原型:

#include <sys/socket.h>
int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

getpeername 函数在addr指向的缓冲区中返回连接到套接字sockfd的对端地址。addrlen参数应该初始化,以指示addr指向的空间量。返回时,它包含返回的名称的实际大小(以字节为单位)。如果提供的缓冲区太小,则名称会被截断。

参数:

  • sockfd:传入参数,要获取IP地址、端口信息的套接字sockfd;
  • addr:传出参数,用来存放获取结果的内存地址;
  • addrlen:传入传出参数,调用是指明第二个参数 addr 指向内存的大小。返回时,它包含套接字地址的实际大小。

返回值:成功返回0,出错返回 -1。

使用场景:
1、tcp服务端通过accept返回的套接字,通过 getpeername 可以获取到客户端的IP地址、端口;
2、其他需要获取对端IP地址或端口的情况。


✨3.2 getpeername 函数例子

这是一个TCP服务端,结合上一小节的客户端一起使用,可以参考第4小节。

// getpeername_sample.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>int main()
{// 1、创建TCP套接字socketint sockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd<0){perror("socket error" );return -1;}// 2、准备服务端ip和端口struct sockaddr_in servaddr;bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons (10086);servaddr.sin_addr.s_addr = INADDR_ANY; // 指定ip地址为 INADDR_ANY,这样要是服务器主机有多个网络接口,服务器进程就可以在任一网络接口上接受客户端的连接// 3、绑定 bindif (bind(sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){perror("bind error" );return -1;}// 4、监听 listenif(listen(sockfd, 10) != 0){perror("listen error");return -1;}printf("TcpSer sockfd=%d, start listening\n",sockfd);char recvline[256];while(1){// 5、获取客户端连接int connfd = accept(sockfd, NULL, NULL);if(connfd < 0){perror("accept error" );return -1;}// 获取 connfd 套接字对端(客户端)的IP地址、端口struct sockaddr_in addr;int addrLen = sizeof(addr);if(0 == getpeername(connfd, (struct sockaddr*)&addr, &addrLen) )printf("getpeername: ip=[%s], port=%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));// 获取 connfd 套接字本端(服务端)的IP地址、端口if(0 == getsockname(connfd, (struct sockaddr*)&addr, &addrLen) )printf("getsockname: ip=[%s], port=%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));// 6、与客户端交换数据,客户端每发数据,会阻塞,此时可以查看连接信息,使用命令`netstat -at | greep 10086`int n = read(connfd, recvline, sizeof(recvline));if(n>0){recvline[n] = 0 ;/*null terminate */printf("recv connfd=%d [%s]\n",connfd,recvline);write(connfd, "Hello,I am tcp server", strlen("Hello,I am tcp server"));}printf("close connfd=%d\n",connfd);close(connfd);}// 7、关闭close(sockfd);return 0;
}

在这里插入图片描述

🎄四、总结

👉本文介绍Linux网络编程中,通过套接字获取IP地址、端口号的两个函数getsockname 和 getpeername,并给出C语言例子加深理解。

上面例子的使用:
编译客户端:gcc getsockname_sample.c -o cli
编译服务端:gcc getpeername_sample.c -o ser
先运行服务端./ser,在另一命令行窗口运行./cli,下面是运行结果:

客户端打印的IP地址和端口号:
在这里插入图片描述
服务端打印的IP地址和端口号:
在这里插入图片描述
运行 netstat -at | grep 10086查看tcp连接状态如下:
在这里插入图片描述
对netstat命令不了解的,可以看文章 netstat 工具详解 | 查看网络连接、查看路由表、查看统计数据

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/442914.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt关于qss文件的添加使用

把ui设计得更加的养眼&#xff0c;肯定需要对控件的属性进行设置&#xff0c;qt中就是关于qss文件的使用。 那么如何创建和添加qss文件呢 1.新建一个文本文件的txt 2.将文本文件的后缀改为qss&#xff08;类比html&#xff09; 3.放置到项目的资源文件夹下 4.添加资源文件 5.在…

推荐系统|排序_MMOE

MMOE MMOE是指Multi-gate Mixture-of-Experts 注意看Expert后面加了s&#xff0c;说明了有多个专家。 而在MMOE中专家是指用来对输入特征计算的神经网络&#xff0c;每个神经网络根据输入计算出来的向量都会有所不同。 MMOE的低层 MMOE的上一层 通过MMOE的低层算出的向量和权…

【排序算法】C语言实现随机快排,巨详细讲解

文章目录 &#x1f680;前言&#x1f680;快排的核心过程partition&#xff08;划分过程&#xff09;&#x1f680;快排1.0&#x1f680;随机快速排序&#x1f680;稳定性 &#x1f680;前言 铁子们好啊&#xff01;继续我们排序算法今天要讲的是快排&#xff0c;通常大家所说…

nop-entropy可逆计算入门(1)

第1步&#xff1a;从大佬的gitee&#xff1a;https://gitee.com/canonical-entropy/nop-entropy下载源码&#xff0c;进行本地编译&#xff0c;具体编译看项目下的readme,想偷懒的可以下载我编译后的jar&#xff0c;放到自己的maven仓库 https://pan.baidu.com/s/15qANnrCh5RV…

C语言字符串操作函数详解①strlen函数的讲解与三种模拟实现方法(建议三连收藏)

目录 ​编辑 前言 1.strlen函数介绍 2.模拟实现strlen 2.1计数器做法 2.2不创建临时变量&#xff0c;通过递归的方法 2.3利用两个指针相减 3.结语 前言 C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量…

Linux文本三剑客-grep

1.grep简介&#xff1a; grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具&#xff0c;它能使用正则表达式搜索文本&#xff0c;并把匹配的行打印出来&#xff0c;都是按行处理的。 grep 最主要…

Linux内核源码

记得看目录哦&#xff01; 1. 为什么要阅读Linux内核2. Linux0.01内核源码3. 阅读linux内核源码技巧4. linux升级内核5. linux的备份和恢复5.1 安装dump和restore5.2 使用dump完成备份5.3 使用restore完成恢复 1. 为什么要阅读Linux内核 2. Linux0.01内核源码 3. 阅读linux内核…

基于Java SSM框架实现影院购票系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现影院购票系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#…

人工智能与机器学习——开启智能时代的里程碑

写在前面 前言人工智能与机器学习的概述监督学习、无监督学习和强化学习的基本原理监督学习&#xff1a;无监督学习&#xff1a;强化学习&#xff1a; 机器学习的算法和方法常见的机器学习算法和方法线性回归&#xff1a;决策树&#xff1a;支持向量机&#xff1a;神经网络&…

React、React Router、JSX 简单入门快速上手

React、React Router、JSX 简单入门快速上手 介绍特点 JSX使用js表达式渲染列表样式控制注意事项 入门脚手架创建react项目安装目录介绍入口文件解析 组件解析介绍函数式组件类组件 事件绑定注意点定义使用事件对象事件处理函数接收额外参数 组件状态状态的定义使用 组件通信父…

dp优化----单调队列解决定长连续区间最小值。 例题:Cashback--- 题解

E. Cashback 题目大意&#xff1a; 思路解析&#xff1a; 如果c1&#xff0c;那么无论如何 答案都为0. 如果c!1&#xff0c;我们考虑如果最优答案有一段区间长度小于c&#xff0c;那么它对答案的贡献值&#xff0c;等于将这个区间划分为长度为1的多个小段&#xff0c; 如果有…

【Midjourney】关于标准模型的几个按钮都有什么用

当用户在Midjourney Bot所在的服务发送/settings命令时就能调出设置窗口&#xff0c;本文将介绍该窗口中的各个按钮都有什么作用。 1.RAW Mode 依照官方的描述来看V5.2模型似乎带有自动优化功能&#xff0c;会对用户输入的关键词空白描述进行补全和优化&#xff0c;以便修复所…