linux socket通讯获取本地的源端口号的实现方法
<p>关于tcp ip网络通讯的资料非常多,tcp ip通过ip数据包模式进行端对端通讯。典型的tcp数据包如下</p>
<p>
<img title="linux socket通讯获取本地的源端口号的实现方法" alt="linux socket通讯获取本地的源端口号的实现方法" src="https://zhuji.jb51.net/uploads/img/202305/5a8137d73b7ae955998825f7ed90967f.jpg"></p>
<p>
可以看到数据包包含了源端口号和目的端口号,客户端socket向服务端发起连接时,系统会给socket随机分配一个源端口号,我们可以通过getsocketname来获取连接成功的socket的原端口信息。</p>
<p>
函数原型</p>
<div class="jb51code">
<div>
<div class="syntaxhighlighterbash" id="highlighter_132079">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="bash comments">#include <sys/socket.h> </code>
</div>
<div class="line number2 index1 alt1">
<code class="bash plain">int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
</div>
<p>
<strong>参数:</strong></p>
<p>
sockfd socket连接的句柄</p>
<p>
addr 网络地址指针,用来存储本地端socket地址信息,</p>
<p>
addrlen addr的空间大小</p>
<p>
返回结果,如果调用成功,返回0,并将本地网络地址信息存放在addr里面,失败返回-1,并通过errno反应错误信息。</p>
<p>
source_port.cpp</p>
<div class="jb51code">
<div>
<div class="syntaxhighlighterbash" id="highlighter_719330">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
<div class="line number8 index7 alt1">
8</div>
<div class="line number9 index8 alt2">
9</div>
<div class="line number10 index9 alt1">
10</div>
<div class="line number11 index10 alt2">
11</div>
<div class="line number12 index11 alt1">
12</div>
<div class="line number13 index12 alt2">
13</div>
<div class="line number14 index13 alt1">
14</div>
<div class="line number15 index14 alt2">
15</div>
<div class="line number16 index15 alt1">
16</div>
<div class="line number17 index16 alt2">
17</div>
<div class="line number18 index17 alt1">
18</div>
<div class="line number19 index18 alt2">
19</div>
<div class="line number20 index19 alt1">
20</div>
<div class="line number21 index20 alt2">
21</div>
<div class="line number22 index21 alt1">
22</div>
<div class="line number23 index22 alt2">
23</div>
<div class="line number24 index23 alt1">
24</div>
<div class="line number25 index24 alt2">
25</div>
<div class="line number26 index25 alt1">
26</div>
<div class="line number27 index26 alt2">
27</div>
<div class="line number28 index27 alt1">
28</div>
<div class="line number29 index28 alt2">
29</div>
<div class="line number30 index29 alt1">
30</div>
<div class="line number31 index30 alt2">
31</div>
<div class="line number32 index31 alt1">
32</div>
<div class="line number33 index32 alt2">
33</div>
<div class="line number34 index33 alt1">
34</div>
<div class="line number35 index34 alt2">
35</div>
<div class="line number36 index35 alt1">
36</div>
<div class="line number37 index36 alt2">
37</div>
<div class="line number38 index37 alt1">
38</div>
<div class="line number39 index38 alt2">
39</div>
<div class="line number40 index39 alt1">
40</div>
<div class="line number41 index40 alt2">
41</div>
<div class="line number42 index41 alt1">
42</div>
<div class="line number43 index42 alt2">
43</div>
<div class="line number44 index43 alt1">
44</div>
<div class="line number45 index44 alt2">
45</div>
<div class="line number46 index45 alt1">
46</div>
<div class="line number47 index46 alt2">
47</div>
<div class="line number48 index47 alt1">
48</div>
<div class="line number49 index48 alt2">
49</div>
<div class="line number50 index49 alt1">
50</div>
<div class="line number51 index50 alt2">
51</div>
<div class="line number52 index51 alt1">
52</div>
<div class="line number53 index52 alt2">
53</div>
<div class="line number54 index53 alt1">
54</div>
<div class="line number55 index54 alt2">
55</div>
<div class="line number56 index55 alt1">
56</div>
<div class="line number57 index56 alt2">
57</div>
<div class="line number58 index57 alt1">
58</div>
<div class="line number59 index58 alt2">
59</div>
<div class="line number60 index59 alt1">
60</div>
<div class="line number61 index60 alt2">
61</div>
<div class="line number62 index61 alt1">
62</div>
<div class="line number63 index62 alt2">
63</div>
<div class="line number64 index63 alt1">
64</div>
<div class="line number65 index64 alt2">
65</div>
<div class="line number66 index65 alt1">
66</div>
<div class="line number67 index66 alt2">
67</div>
<div class="line number68 index67 alt1">
68</div>
<div class="line number69 index68 alt2">
69</div>
<div class="line number70 index69 alt1">
70</div>
<div class="line number71 index70 alt2">
71</div>
<div class="line number72 index71 alt1">
72</div>
<div class="line number73 index72 alt2">
73</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="bash comments">#include <cstring> </code>
</div>
<div class="line number2 index1 alt1">
<code class="bash comments">#include <cstdio> </code>
</div>
<div class="line number3 index2 alt2">
<code class="bash comments">#include <cstdlib> </code>
</div>
<div class="line number4 index3 alt1">
<code class="bash comments">#include <sys/socket.h> </code>
</div>
<div class="line number5 index4 alt2">
<code class="bash comments">#include <sys/types.h> </code>
</div>
<div class="line number6 index5 alt1">
<code class="bash comments">#include <netinet/in.h> </code>
</div>
<div class="line number7 index6 alt2">
<code class="bash comments">#include <netinet/ip.h> </code>
</div>
<div class="line number8 index7 alt1">
<code class="bash comments">#include <netdb.h> </code>
</div>
<div class="line number9 index8 alt2">
<code class="bash comments">#include <errno.h> </code>
</div>
<div class="line number10 index9 alt1">
<code class="bash comments">#include <unistd.h> </code>
</div>
<div class="line number11 index10 alt2">
<code class="bash comments">#include <arpa/inet.h> </code>
</div>
<div class="line number12 index11 alt1">
<code class="bash plain">void safe_close(int &sock); </code>
</div>
<div class="line number13 index12 alt2">
<code class="bash plain">int main(int argc, char *argv[]) { </code>
</div>
<div class="line number14 index13 alt1">
<code class="bash spaces"> </code><code class="bash plain">int sockfd = 0, n = 0; </code>
</div>
<div class="line number15 index14 alt2">
<code class="bash spaces"> </code><code class="bash plain">socklen_t len = 0; </code>
</div>
<div class="line number16 index15 alt1">
<code class="bash spaces"> </code><code class="bash plain">char host = {0}; </code>
</div>
<div class="line number17 index16 alt2">
<code class="bash spaces"> </code><code class="bash plain">char buf = {0}; </code>
</div>
<div class="line number18 index17 alt1">
<code class="bash spaces"> </code><code class="bash plain">struct hostent *server; </code>
</div>
<div class="line number19 index18 alt2">
<code class="bash spaces"> </code><code class="bash plain">struct sockaddr_in serv_addr, loc_addr; </code>
</div>
<div class="line number20 index19 alt1">
<code class="bash spaces"> </code><code class="bash keyword">if</code> <code class="bash plain">(argc < 2) { </code>
</div>
<div class="line number21 index20 alt2">
<code class="bash spaces"> </code><code class="bash functions">printf</code><code class="bash plain">(</code><code class="bash string">"please input host name\n"</code><code class="bash plain">); </code>
</div>
<div class="line number22 index21 alt1">
<code class="bash spaces"> </code><code class="bash functions">exit</code><code class="bash plain">(-1); </code>
</div>
<div class="line number23 index22 alt2">
<code class="bash spaces"> </code><code class="bash plain">} </code>
</div>
<div class="line number24 index23 alt1">
<code class="bash spaces"> </code><code class="bash plain">strncpy(host, argv, sizeof(host)); </code>
</div>
<div class="line number25 index24 alt2">
<code class="bash spaces"> </code><code class="bash plain">server = gethostbyname(host);</code><code class="bash plain">//</code> <code class="bash plain">判断输入的域名是否正确 </code>
</div>
<div class="line number26 index25 alt1">
<code class="bash spaces"> </code><code class="bash keyword">if</code> <code class="bash plain">(null == server) { </code>
</div>
<div class="line number27 index26 alt2">
<code class="bash spaces"> </code><code class="bash functions">printf</code><code class="bash plain">(</code><code class="bash string">"find host: %s failed.\n"</code><code class="bash plain">, host); </code>
</div>
<div class="line number28 index27 alt1">
<code class="bash spaces"> </code><code class="bash functions">exit</code><code class="bash plain">(-1); </code>
</div>
<div class="line number29 index28 alt2">
<code class="bash spaces"> </code><code class="bash plain">} </code>
</div>
<div class="line number30 index29 alt1">
<code class="bash spaces"> </code><code class="bash keyword">if</code> <code class="bash plain">(-1 == (sockfd = socket(af_inet, sock_stream, 0))) {</code><code class="bash plain">//</code> <code class="bash plain">创建socket </code>
</div>
<div class="line number31 index30 alt2">
<code class="bash spaces"> </code><code class="bash plain">memset(buf, 0, sizeof(buf)); </code>
</div>
<div class="line number32 index31 alt1">
<code class="bash spaces"> </code><code class="bash plain">snprintf(buf, sizeof(buf), </code><code class="bash string">"new socket failed. errno: %d, error: %s"</code><code class="bash plain">, errno, strerror(errno)); </code>
</div>
<div class="line number33 index32 alt2">
<code class="bash spaces"> </code><code class="bash plain">perror(buf); </code>
</div>
<div class="line number34 index33 alt1">
<code class="bash spaces"> </code><code class="bash functions">exit</code><code class="bash plain">(-1); </code>
</div>
<div class="line number35 index34 alt2">
<code class="bash spaces"> </code><code class="bash plain">} </code>
</div>
<div class="line number36 index35 alt1">
<code class="bash spaces"> </code><code class="bash plain">memset(&serv_addr, 0, sizeof(serv_addr)); </code>
</div>
<div class="line number37 index36 alt2">
<code class="bash spaces"> </code><code class="bash plain">serv_addr.sin_family = af_inet; </code>
</div>
<div class="line number38 index37 alt1">
<code class="bash spaces"> </code><code class="bash plain">serv_addr.sin_port = htons(80);</code><code class="bash plain">//</code> <code class="bash plain">http标准端口号 </code>
</div>
<div class="line number39 index38 alt2">
<code class="bash spaces"> </code><code class="bash plain">memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length); </code>
</div>
<div class="line number40 index39 alt1">
<code class="bash spaces"> </code><code class="bash keyword">if</code> <code class="bash plain">(-1 == inet_pton(af_inet, host, &serv_addr.sin_addr)) { </code>
</div>
<div class="line number41 index40 alt2">
<code class="bash spaces"> </code><code class="bash plain">memset(buf, 0, sizeof(buf)); </code>
</div>
<div class="line number42 index41 alt1">
<code class="bash spaces"> </code><code class="bash plain">snprintf(buf, sizeof(buf), </code><code class="bash string">"inet_pton failed. errno: %d, error: %s"</code><code class="bash plain">, errno, strerror(errno)); </code>
</div>
<div class="line number43 index42 alt2">
<code class="bash spaces"> </code><code class="bash plain">perror(buf); </code>
</div>
<div class="line number44 index43 alt1">
<code class="bash spaces"> </code><code class="bash functions">exit</code><code class="bash plain">(-1); </code>
</div>
<div class="line number45 index44 alt2">
<code class="bash spaces"> </code><code class="bash plain">} </code>
</div>
<div class="line number46 index45 alt1">
<code class="bash spaces"> </code><code class="bash keyword">if</code> <code class="bash plain">(-1 == connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {</code><code class="bash plain">//</code> <code class="bash plain">连接socket </code>
</div>
<div class="line number47 index46 alt2">
<code class="bash spaces"> </code><code class="bash plain">memset(buf, 0, sizeof(buf)); </code>
</div>
<div class="line number48 index47 alt1">
<code class="bash spaces"> </code><code class="bash plain">snprintf(buf, sizeof(buf), </code><code class="bash string">"connect socket failed. errno: %d, error: %s"</code><code class="bash plain">, errno, strerror(errno)); </code>
</div>
<div class="line number49 index48 alt2">
<code class="bash spaces"> </code><code class="bash plain">perror(buf); </code>
</div>
<div class="line number50 index49 alt1">
<code class="bash spaces"> </code><code class="bash functions">exit</code><code class="bash plain">(-1); </code>
</div>
<div class="line number51 index50 alt2">
<code class="bash spaces"> </code><code class="bash plain">} </code>
</div>
<div class="line number52 index51 alt1">
<code class="bash spaces"> </code><code class="bash functions">printf</code><code class="bash plain">(</code><code class="bash string">"connect to %s success.\n"</code><code class="bash plain">, host); </code>
</div>
<div class="line number53 index52 alt2">
<code class="bash spaces"> </code><code class="bash plain">len = sizeof(sizeof(loc_addr)); </code>
</div>
<div class="line number54 index53 alt1">
<code class="bash spaces"> </code><code class="bash plain">memset(&loc_addr, 0, len); </code>
</div>
<div class="line number55 index54 alt2">
<code class="bash spaces"> </code><code class="bash keyword">if</code> <code class="bash plain">(-1 == getsockname(sockfd, (struct sockaddr *)&loc_addr, &len)) {</code><code class="bash plain">//</code> <code class="bash plain">获取socket绑定的本地address信息 </code>
</div>
<div class="line number56 index55 alt1">
<code class="bash spaces"> </code><code class="bash plain">memset(buf, 0, sizeof(buf)); </code>
</div>
<div class="line number57 index56 alt2">
<code class="bash spaces"> </code><code class="bash plain">snprintf(buf, sizeof(buf), </code><code class="bash string">"get socket name failed. errno: %d, error: %s"</code><code class="bash plain">, errno, strerror(errno)); </code>
</div>
<div class="line number58 index57 alt1">
<code class="bash spaces"> </code><code class="bash plain">perror(buf); </code>
</div>
<div class="line number59 index58 alt2">
<code class="bash spaces"> </code><code class="bash plain">safe_close(sockfd); </code>
</div>
<div class="line number60 index59 alt1">
<code class="bash spaces"> </code><code class="bash functions">exit</code><code class="bash plain">(-1); </code>
</div>
<div class="line number61 index60 alt2">
<code class="bash spaces"> </code><code class="bash plain">} </code>
</div>
<div class="line number62 index61 alt1">
<code class="bash spaces"> </code><code class="bash keyword">if</code> <code class="bash plain">(loc_addr.sin_family == af_inet) {</code><code class="bash plain">//</code> <code class="bash plain">打印信息 </code>
</div>
<div class="line number63 index62 alt2">
<code class="bash spaces"> </code><code class="bash functions">printf</code><code class="bash plain">(</code><code class="bash string">"local port: %u\n"</code><code class="bash plain">, ntohs(loc_addr.sin_port)); </code>
</div>
<div class="line number64 index63 alt1">
<code class="bash spaces"> </code><code class="bash plain">} </code>
</div>
<div class="line number65 index64 alt2">
<code class="bash spaces"> </code><code class="bash plain">safe_close(sockfd); </code>
</div>
<div class="line number66 index65 alt1">
<code class="bash spaces"> </code><code class="bash keyword">return</code> <code class="bash plain">0; </code>
</div>
<div class="line number67 index66 alt2">
<code class="bash plain">} </code>
</div>
<div class="line number68 index67 alt1">
<code class="bash plain">void safe_close(int &sock) { </code>
</div>
<div class="line number69 index68 alt2">
<code class="bash spaces"> </code><code class="bash keyword">if</code> <code class="bash plain">(-1 != sock) { </code>
</div>
<div class="line number70 index69 alt1">
<code class="bash spaces"> </code><code class="bash functions">shutdown</code><code class="bash plain">(sock, shut_rdwr); </code>
</div>
<div class="line number71 index70 alt2">
<code class="bash spaces"> </code><code class="bash plain">sock = -1; </code>
</div>
<div class="line number72 index71 alt1">
<code class="bash spaces"> </code><code class="bash plain">} </code>
</div>
<div class="line number73 index72 alt2">
<code class="bash plain">}</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
</div>
<p>
本程序首先会启动一个socket连接一个普通的http服务器(baidu,qq,163,csdn),当socket连通时就通过getsocketname获取连接绑定的本地地址,并通过该地址获取源端口号。</p>
<p>
终端1: 编译及运行</p>
<div class="jb51code">
<div>
<div class="syntaxhighlighterbash" id="highlighter_93866">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="bash plain">$ g++ source_port.cpp</code>
</div>
<div class="line number2 index1 alt1">
<code class="bash plain">$ .</code><code class="bash plain">/a</code><code class="bash plain">.out www.baidu.com</code>
</div>
<div class="line number3 index2 alt2">
<code class="bash plain">connect to www.baidu.com success.</code>
</div>
<div class="line number4 index3 alt1">
<code class="bash functions">local</code> <code class="bash plain">port: 39702</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
</div>
<p>
终端2: 通过tcpdump抓包验证</p>
<div class="jb51code">
<div>
<div class="syntaxhighlighterbash" id="highlighter_900978">
<div class="toolbar">
<span>?</span>
</div>
<table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
<div class="line number1 index0 alt2">
1</div>
<div class="line number2 index1 alt1">
2</div>
<div class="line number3 index2 alt2">
3</div>
<div class="line number4 index3 alt1">
4</div>
<div class="line number5 index4 alt2">
5</div>
<div class="line number6 index5 alt1">
6</div>
<div class="line number7 index6 alt2">
7</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2">
<code class="bash plain">$ </code><code class="bash functions">sudo</code> <code class="bash plain">tcpdump host www.baidu.com -</code><code class="bash functions">v</code>
</div>
<div class="line number2 index1 alt1">
<code class="bash plain">tcpdump: listening on eth0, link-</code><code class="bash functions">type</code> <code class="bash plain">en10mb (ethernet), capture size 65535 bytes</code>
</div>
<div class="line number3 index2 alt2">
<code class="bash plain">18:38:32.381448 ip (tos 0x0, ttl 64, </code><code class="bash functions">id</code> <code class="bash plain">35033, offset 0, flags [</code><code class="bash functions">df</code><code class="bash plain">], proto tcp (6), length 60)</code>
</div>
<div class="line number4 index3 alt1">
<code class="bash plain">icentos.39702 > 220.181.111.188.http: flags , cksum 0x8cd2 (incorrect -> 0x596a), </code><code class="bash functions">seq</code> <code class="bash plain">2381397554, win 29200, options , length 0</code>
</div>
<div class="line number5 index4 alt2">
<code class="bash plain">18:38:32.425904 ip (tos 0x0, ttl 55, </code><code class="bash functions">id</code> <code class="bash plain">35033, offset 0, flags [</code><code class="bash functions">df</code><code class="bash plain">], proto tcp (6), length 60)</code>
</div>
<div class="line number6 index5 alt1">
<code class="bash plain">220.181.111.188.http > icentos.39702: flags , cksum 0xc315 (correct), </code><code class="bash functions">seq</code> <code class="bash plain">3561856904, ack 2381397555, win 8192, options , length 0</code>
</div>
<div class="line number7 index6 alt2">
<code class="bash plain">18:38:32.425930 ip (tos 0x0, ttl 64, </code><code class="bash functions">id</code> <code class="bash plain">35034, offset 0, flags [</code><code class="bash functions">df</code><code class="bash plain">], proto tcp (6), length 40)</code>
</div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
</div>
<p>
对比终端一和终端二表明获取的源端口地址是正确的。</p>
<p>
<span><strong>总结</strong></span></p>
<p>
以上所述是小编给大家介绍的linux socket通讯获取本地的源端口号的实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!</p>
<p>
原文链接:http://blog.csdn.net/sweettool/article/details/78078750</p>
頁:
[1]