linux中關于socket通訊獲取本地的源端口號的實現方法

這篇文章主要介紹了linux socket通訊獲取本地的源端口號的相關資料,需要的朋友可以參考下

關于TCP IP網絡通訊的資料非常多,TCP IP通過IP數據包模式進行端對端通訊。典型的TCP數據包如下

linux中關于socket通訊獲取本地的源端口號的實現方法

可以看到數據包包含了源端口號和目的端口號,客戶端socket向服務端發起連接時,系統會給socket隨機分配一個源端口號,我們可以通過getsocketname來獲取連接成功的socket的原端口信息。

函數原型

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

參數:

sockfd socket連接的句柄

addr 網絡地址指針,用來存儲本地端socket地址信息,

addrlen addr的空間大小

返回結果,如果調用成功,返回0,并將本地網絡地址信息存放在addr里面,失敗返回-1,并通過errno反應錯誤信息。

source_port.cpp

#include?<cstring>?  #include?<cstdio>?  #include?<cstdlib>?  #include?<sys>?  #include?<sys>?  #include?<netinet>?  #include?<netinet>?  #include?<netdb.h>?  #include?<errno.h>?  #include?<unistd.h>?  #include?<arpa>?  void?safe_close(int?&amp;sock);?  int?main(int?argc,?char?*argv[])?{?  ?int?sockfd?=?0,?n?=?0;?  ?socklen_t?len?=?0;?  ?char?host[512]?=?{0};?  ?char?buf[1024]?=?{0};?  ?struct?hostent?*server;?  ?struct?sockaddr_in?serv_addr,?loc_addr;?  ?if?(argc?h_addr,?server-&gt;h_length);?  ?if?(-1?==?inet_pton(AF_INET,?host,?&amp;serv_addr.sin_addr))?{?  ??memset(buf,?0,?sizeof(buf));?  ??snprintf(buf,?sizeof(buf),?"inet_pton?failed.?errno:?%d,?error:?%s",?errno,?strerror(errno));?  ??perror(buf);?  ??exit(-1);?  ?}?  ?if?(-1?==?connect(sockfd,?(struct?sockaddr?*)&amp;serv_addr,?sizeof(serv_addr)))?{//?連接socket?  ??memset(buf,?0,?sizeof(buf));?  ??snprintf(buf,?sizeof(buf),?"connect?socket?failed.?errno:?%d,?error:?%s",?errno,?strerror(errno));?  ??perror(buf);?  ??exit(-1);?  ?}?  ?printf("connect?to?%s?success.n",?host);?  ?len?=?sizeof(sizeof(loc_addr));?  ?memset(&amp;loc_addr,?0,?len);?  ?if?(-1?==?getsockname(sockfd,?(struct?sockaddr?*)&amp;loc_addr,?&amp;len))?{//?獲取socket綁定的本地address信息?  ??memset(buf,?0,?sizeof(buf));?  ??snprintf(buf,?sizeof(buf),?"get?socket?name?failed.?errno:?%d,?error:?%s",?errno,?strerror(errno));?  ??perror(buf);?  ??safe_close(sockfd);?  ??exit(-1);?  ?}?  ?if?(loc_addr.sin_family?==?AF_INET)?{//?打印信息?  ??printf("local?port:?%un",?ntohs(loc_addr.sin_port));?  ?}?  ?safe_close(sockfd);?  ?return?0;?  }?  void?safe_close(int?&amp;sock)?{?  ?if?(-1?!=?sock)?{?  ??shutdown(sock,?SHUT_RDWR);?  ??sock?=?-1;?  ?}?  }</arpa></unistd.h></errno.h></netdb.h></netinet></netinet></sys></sys></cstdlib></cstdio></cstring>

本程序首先會啟動一個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?&gt;?220.181.111.188.http:?Flags?[S],?cksum?0x8cd2?(incorrect?-&gt;?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?&gt;?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)

對比終端一和終端二表明獲取的源端口地址是正確的。

總結

? 版權聲明
THE END
喜歡就支持一下吧
點贊7 分享