linux socket通讯如何获取本地的源端口号

关于TCP IP网络通讯的资料非常多,TCP IP通过IP数据包模式进行端对端通讯。典型的TCP数据包如下

可以看到数据包包含了源端口号和目的端口号,客户端socket向服务端发起连接时,系统会给socket随机分配一个源端口号,我们可以通过getsocketname来获取连接成功的socket的原端口信息。

函数原型

[cpp] view plain copy

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

参数:

sockfd socket连接的句柄

addr 网络地址指针,用来存储本地端socket地址信息,

addrlen addr的空间大小

返回结果,如果调用成功,返回0,并将本地网络地址信息存放在addr里面,失败返回-1,并通过errno反应错误信息。

source_port.cpp

[cpp] view plain copy

  1. #include <cstring>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <sys/socket.h>
  5. #include <sys/types.h>
  6. #include <netinet/in.h>
  7. #include <netinet/ip.h>
  8. #include <netdb.h>
  9. #include <errno.h>
  10. #include <unistd.h>
  11. #include <arpa/inet.h>
  12. void safe_close(int &sock);
  13. int main(int argc, char *argv[]) {
  14. int sockfd = 0, n = 0;
  15. socklen_t len = 0;
  16. char host[512] = {0};
  17. char buf[1024] = {0};
  18. struct hostent *server;
  19. struct sockaddr_in serv_addr, loc_addr;
  20. if (argc < 2) {
  21. printf("Please input host name\n");
  22. exit(-1);
  23. }
  24. strncpy(host, argv[1], sizeof(host));
  25. server = gethostbyname(host);// 判断输入的域名是否正确
  26. if (NULL == server) {
  27. printf("find host: %s failed.\n", host);
  28. exit(-1);
  29. }
  30. if (-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0))) {// 创建socket
  31. memset(buf, 0, sizeof(buf));
  32. snprintf(buf, sizeof(buf), "new socket failed. errno: %d, error: %s", errno, strerror(errno));
  33. perror(buf);
  34. exit(-1);
  35. }
  36. memset(&serv_addr, 0, sizeof(serv_addr));
  37. serv_addr.sin_family = AF_INET;
  38. serv_addr.sin_port = htons(80);// http标准端口号
  39. memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
  40. if (-1 == inet_pton(AF_INET, host, &serv_addr.sin_addr)) {
  41. memset(buf, 0, sizeof(buf));
  42. snprintf(buf, sizeof(buf), "inet_pton failed. errno: %d, error: %s", errno, strerror(errno));
  43. perror(buf);
  44. exit(-1);
  45. }
  46. if (-1 == connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {// 连接socket
  47. memset(buf, 0, sizeof(buf));
  48. snprintf(buf, sizeof(buf), "connect socket failed. errno: %d, error: %s", errno, strerror(errno));
  49. perror(buf);
  50. exit(-1);
  51. }
  52. printf("connect to %s success.\n", host);
  53. len = sizeof(sizeof(loc_addr));
  54. memset(&loc_addr, 0, len);
  55. if (-1 == getsockname(sockfd, (struct sockaddr *)&loc_addr, &len)) {// 获取socket绑定的本地address信息
  56. memset(buf, 0, sizeof(buf));
  57. snprintf(buf, sizeof(buf), "get socket name failed. errno: %d, error: %s", errno, strerror(errno));
  58. perror(buf);
  59. safe_close(sockfd);
  60. exit(-1);
  61. }
  62. if (loc_addr.sin_family == AF_INET) {// 打印信息
  63. printf("local port: %u\n", ntohs(loc_addr.sin_port));
  64. }
  65. safe_close(sockfd);
  66. return 0;
  67. }
  68. void safe_close(int &sock) {
  69. if (-1 != sock) {
  70. shutdown(sock, SHUT_RDWR);
  71. sock = -1;
  72. }
  73. }

本程序首先会启动一个socket连接一个普通的http服务器(baidu,qq,163,csdn),当socket连通时就通过getsocketname获取连接绑定的本地地址,并通过该地址获取源端口号。

终端1: 编译及运行

$ g++ source_port.cpp

$ ./a.out www.baidu.com

connect to www.baidu.com success.

local port: 39702

终端2: 通过tcpdump抓包验证

$ sudo tcpdump host www.baidu.com -v

tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

18:38:32.381448 IP (tos 0x0, ttl 64, id 35033, offset 0, flags [DF], proto TCP (6), length 60)

icentos.39702 > 220.181.111.188.http: Flags [S], cksum 0x8cd2 (incorrect -> 0x596a), seq 2381397554, win 29200, options [mss 1460,sackOK,TS val 3513497323 ecr 0,nop,wscale 7], length 0

18:38:32.425904 IP (tos 0x0, ttl 55, id 35033, offset 0, flags [DF], proto TCP (6), length 60)

220.181.111.188.http > icentos.39702: Flags [S.], cksum 0xc315 (correct), seq 3561856904, ack 2381397555, win 8192, options [mss 1424,sackOK,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,wscale 5], length 0

18:38:32.425930 IP (tos 0x0, ttl 64, id 35034, offset 0, flags [DF], proto TCP (6), length 40)

对比终端一和终端二表明获取的源端口地址是正确的。

时间: 2024-10-24 22:14:35

linux socket通讯如何获取本地的源端口号的相关文章

windows 与 Linux SOCKET通讯

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 windows client 端口 // Def_win_client_socket_test.cpp :

linux运维之配置本地yum源

在本地虚拟机搭建linux测试环境,有时候受网络限制,无法通过外网来使用yum源,而我们本地又有ISO镜像文件,所有常用的rpm包在iso/server里面都能找到,如果使用rpm安装,安装的时候总是存在大量的依赖包,实在麻烦,所以配置一个本地yum源是非常有必要的,以下是配置过程: 1.在虚拟机的设置里面加载对应的ISO镜像文件 2.创建一个目录,并挂载ISO镜像 mkdir -p  /mnt/cdrom mount -o loop /dev/cdrom /mnt/cdrom 3.配置yum源

Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip

获取本地 ip 地址,mac,通过域名获取对应的 ip, 是网络编程可能遇到的比较常见的操作了,所以总结如下(封装了3个函数), 直接上代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <netdb.h> #include <net/if.h> #inc

Linux学习-防火墙-Selinux-配置本地YUM源

关闭防火墙并设置开机不启动 systemctl status firewalld.service #查看firewalld状态systemctl stop firewalld #关闭systemctl start firewalld #开启systemctl disable firewalld #开机自动关闭 //RHLE7chkconfig --list|grep network #查看开机是否启动 //RHLE6systemctl enable firewalld #开机自动启动 临时和永久

nginx模块编程之获取客户ip及端口号

ngx_request_t结构体中有一个connection定义,该定义指向一个ngx_connection_t的结构体: 结构体定义如下: 1 struct ngx_connection_s { 2 void *data; 3 ngx_event_t *read; 4 ngx_event_t *write; 5 6 ngx_socket_t fd; 7 8 ngx_recv_pt recv; 9 ngx_send_pt send; 10 ngx_recv_chain_pt recv_chain

Linux用ios镜像制作本地yum源

本次使用的软件为RHEL 6.5和VMware Workstation10 挂载iso镜像   (创建挂载目录,再挂载,进入目录查看是否挂载成功) (根据相应情况,镜像文件一般为sr0 我电脑里是第二个为6.5镜像文件 故为输入sr1) 创建/yum文件,再将Server和Packages复制到/yum中 (注意准备足够大的空间!3G稳当吧) mkdir /yum cp -rv /mnt/cdrom/Server /yum cp -rv /mnt/cdrom/Packages /yum 进入Pa

linux socket编程:简易客户端与服务端

什么是socket? socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作.其实socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket的作用是用于网络通讯,网络通讯一般指的是不同主机之间的进程通讯,比如我电脑上的qq和你电脑上的qq实现通讯,都是进程之间发送数据. 在本地用pid标识一个进

linux开启防火墙端口和查看,开启相关端口号

防火墙开启与关闭(即时生效,重启后失效): $ sudo service iptables start            #开启 $ sudo service iptables stop            #关闭 防火墙开启与关闭(重启后生效): $ sudo chkconfig iptables on $ sudo chkconfig iptables off 开启相关端口: 修改 /etc/sysconfig/iptables 文件,添加以下内容: -A INPUT -p tcp -

Linux下编程获取本地IP地址的常见方法

转载于:http://blog.csdn.net/k346k346/article/details/48231933 在进行linux网络编程时,经常用到本机IP地址.本文罗列一下常见方法,以备不时之需. 获取本机IP地址,是一个相当灵活的操作,原因是网络地址的设置非常灵活而且都是允许用户进行个性化设置的.比如一台计算机上可以有多块物理网卡或者虚拟网卡,一个网卡上可以绑定多个IP地址,用户可以为网卡设置别名,可以重命名网卡.用户计算机所在网络拓扑结构未知,主机名设置是一个可选项,并且同样可以为一