首页 > 系统相关 >linux getsockname和getpeername使用

linux getsockname和getpeername使用

时间:2022-11-15 16:31:45浏览次数:40  
标签:struct int 地址 getsockname linux getpeername include inet 函数


getsockname和getpeername函数

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

定义如下:

1. #include<sys/socket.h>  
2.
3. int getsockname(int sockfd, struct sockaddr *localaddr, socklen_t *addrlen);
4.
5. int getpeername(int sockfd, struct sockaddr *peeraddr, socklen_t *addrlen);

对于这两个函数,如果函数调用成功,则返回0,如果调用出错,则返回-1。

使用这两个函数,我们可以通过套接字描述符来获取自己的IP地址和连接对端的IP地址,如在未调用bind函数的TCP客户端程序上,可以通过调用getsockname()函数获取由内核赋予该连接的本地IP地址和本地端口号,还可以在TCP的服务器端accept成功后,通过getpeername()函数来获取当前连接的客户端的IP地址和端口号。

如下面的客户端-服务器程序:

服务器端代码


1. /*服务器端*/  
2. #define MAXLINE 4096
3. #define PORT 6563
4. #define LISTENQ 1024
5. #include<stdio.h>
6. #include<sys/socket.h>
7. #include<netinet/in.h>
8. #include<unistd.h>
9. #include<string.h>
10. #include<arpa/inet.h>
11.
12. int main() {
13. int listenfd, connfd;
14. struct sockaddr_in servaddr;//服务器绑定的地址
15. struct sockaddr_in listendAddr, connectedAddr, peerAddr;//分别表示监听的地址,连接的本地地址,连接的对端地址
16. int listendAddrLen, connectedAddrLen, peerLen;
17. char ipAddr[INET_ADDRSTRLEN];//保存点分十进制的地址
18. listenfd = socket(AF_INET, SOCK_STREAM, 0);
19. sizeof(servaddr));
20.
21. servaddr.sin_family = AF_INET;
22. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
23. servaddr.sin_port = htons(PORT);
24.
25. struct sockaddr*)&servaddr, sizeof(servaddr));//服务器端绑定地址
26.
27. listen(listenfd, LISTENQ);
28. sizeof(listendAddr);
29. struct sockaddr *)&listendAddr, &listendAddrLen);//获取监听的地址和端口
30. "listen address = %s:%d\n", inet_ntoa(listendAddr.sin_addr), ntohs(listendAddr.sin_port));
31.
32. while(1) {
33. struct sockaddr *)NULL, NULL);
34. sizeof(connectedAddr);
35. struct sockaddr *)&connectedAddr, &connectedAddrLen);//获取connfd表示的连接上的本地地址
36. "connected server address = %s:%d\n", inet_ntoa(connectedAddr.sin_addr), ntohs(connectedAddr.sin_port));
37. struct sockaddr *)&peerAddr, &peerLen); //获取connfd表示的连接上的对端地址
38. "connected peer address = %s:%d\n", inet_ntop(AF_INET, &peerAddr.sin_addr, ipAddr, sizeof(ipAddr)), ntohs(peerAddr.sin_port));
39. }
40. return 0;
41. }


上面的代码中,在调用listen函数之后就获取监听套接字描述符对应的本地地址,在accept()函数后,由于accept返回了一个套接字描述符connfd用于表示该连接,所以可以对这个connfd调用getsockname函数和getpeername函数,分别获取内核赋予该连接的本地IP地址和连接的对端地址。

客户端代码


1. /*客户端*/  
2. #define PORT 6563
3. #include<stdio.h>
4. #include<sys/socket.h>
5. #include<netinet/in.h>
6. #include<unistd.h>
7. #include<string.h>
8. #include<arpa/inet.h>
9.
10. int main(int argc, char **argv) {
11. struct sockaddr_in servaddr;//服务器端地址
12. struct sockaddr_in clientAddr;//客户端地址
13. int sockfd;
14. int clientAddrLen = sizeof(clientAddr);
15. char ipAddress[INET_ADDRSTRLEN];//保存点分十进制的ip地址
16.
17. if(argc < 2) {
18. "parameter error");
19. }
20.
21. sockfd = socket(AF_INET, SOCK_STREAM, 0);
22. sizeof(servaddr));
23. servaddr.sin_family = AF_INET;
24. servaddr.sin_port = htons(PORT);
25. if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
26. "server address error\n");//地址参数不合法
27. }
28.
29. struct sockaddr *)&servaddr, sizeof(servaddr));//向服务器端发起连接请求
30.
31. struct sockaddr*)&clientAddr, &clientAddrLen);//获取sockfd表示的连接上的本地地址
32.
33. "client:client ddress = %s:%d\n", inet_ntop(AF_INET, &clientAddr.sin_addr, ipAddress, sizeof(ipAddress)), ntohs(clientAddr.sin_port));
34. return 0;
35. }

在客户端的代码中,调用connect函数后,即可调用getsockname来获连接上的本地地址。

代码的运行结果如下:

服务区端输出

linux getsockname和getpeername使用_ip地址

客户端输出

linux getsockname和getpeername使用_ip地址_02

从上面的代码中可以看到,服务器端listenfd套接字描述符对应的地址即为绑定的通配IP地址和指定的端口,而connfd套接字描述符对应的连接的服务器端的地址为内核赋予的地址和用户指定的端口。

上面的客户端与服务器端的代码中使用了函数inet_ntoa,inet_pton对32位的地址进行转换,其中inet_ntoa是较老的函数,与它一起的还有函数inet_addr和inet_ntoa,这三个函数的定义如下:

1. #include<arpa/inet.h>  
2.
3. int inet_aton(const char *strptr, struct in_addr *addrptr);
4.
5. in_addr_t inet_addr(const char *strptr);
6.
7. char *inet_ntoa(struct in_addr inaddr);

inet_aton与inet_addr函数的功能类似,都是将点分十进制的字符串表示的IP地址转换成32位的网络字节序的IPv4地址。

inet_ntoa函数将32位的网络字节序的IPv4地址转换成点分十进制的字符串表示的IP地址,inet_addr函数已被废弃,并且这三个函数只针对IPv4地址有效,在点分十进制数串和32位的网络字节序二进制值间进行转换,如果要对于IPv4和IPv6都适用,那么使用下面两个函数:

1. #include<arpa/inet.h>  
2.
3. int inet_pton(int family, const char *strptr, void *addrptr);
4.
5. const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);

函数中的p和n分别代表表达式(presentation)和数值(numeric)

所以inet_pton函数将strptr指针所指的字符串转换为网络地址(IPv4和IPv6),再将地址保存到addrptr指向的结构体中,inet_ntop将网络地址转为字符串表示的地址,结果存放在strptr中,len参数是strptr的大小。
这两个函数支持IPv4和IPv6,所以需要通过参数family来指定,当前要转换的是IPv4地址还是IPv6地址。

Reference

《UNIX网络编程 卷1:套接字联网API(第3版)》


标签:struct,int,地址,getsockname,linux,getpeername,include,inet,函数
From: https://blog.51cto.com/u_15797962/5853182

相关文章

  • linux内存介绍
    [yunwei@192~]#freetotalusedfreesharedbuff/cacheavailableMem:323601921512724010232428767304......
  • linux_命令行助手:(manpages supplement)/获取linux命令用法示例的若干辅助命令行工具
    文章目录​​linux_命令行助手:(manpagessupplement)/获取linux命令用法示例的若干辅助命令行工具(cheat/tldr)​​​​references​​​​我的推荐​​​​ltdr(pythonpi......
  • linux buildroot平台添加gzip
    linuxbuildroot平台添加gzip在ubuntu中通过tar-zcvfxxxxxx.tar.gzxxxxxx命令压缩的文件,在开发板上无法解压,弹出如下提示:待添加发现是buildroot默认没有gzip,需要打......
  • 初识Linux(九)------ 学习Shell Scripts
    基本上,shellscript有点像是早期的批处理文件,亦即是将一些指令汇整起来一次执行,但是Shellscript拥有更强大的功能,那就是他可以进行类似程序(program)的编写,并且不......
  • linux开放端口命令
    linux系统中控制端口的开启与关闭可以由命令来执行。linux下开放端口命令的相关知识:linux开放端口命令1打开指定端口:/sbin/iptables-IINPUT-ptcp--dport80-jACC......
  • linux部署java环境
    一、进入到下载目录cd/usr/local/src二、下载Java下载地址JavaDownloads|Oracle下载完后执行下面这个命令然后选择到下载的文件后通过xshell上传上去或者通过......
  • linux Buildroot的syslogd配置
    linuxBuildroot的syslogd配置1、简介syslogd可以负责记录系统运作中,kernel或应用程式产生的各种讯息。这些讯息被写入到系统的纪录档中,让管理人员,进行故障排除、追踪尝......
  • elasticsearch安装(Linux)
    1.下载安装包官网下载,下载地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch将安装包上传到服务器#创建文件mkdirelasticsearch  2.创建......
  • Linux启动流程rcN.d rcS.d rc.local等
    1环境当前系统环境为:Linuxmintmate17.1(基于ubuntu14.04的衍生版)备注:/etc/rc.d文件夹中的脚本文件的链接目标为:/etc/init.d文件夹下的脚本(为系统运行级别‘数字’......
  • Linux-终端命令格式-笔记
    目标了解终端命令格式知道如何查阅终端命令帮助信息01.终端命令格式command[-options][parameter]说明:​​command​​:命令名,相应功能的英文单词或单词的缩写​​[-optio......