【工具】ubuntu16安装sendip发包工具,模拟发送tcp/udp/icmp报文

写在开篇,最近因为测试需求,要使用Linux虚机模拟tcp/udp等协议报文,网上一搜,工具很多,文档不少,看着也不难,结果一装一堆报错,令人头秃。。。

最后翻到这篇文章真的是太绝了,瞬间解决安装报错问题,也才发现原来其实并不需要下载安装包再解压之类的操作就可以实现安装使用。。。

原文链接:https://blog.csdn.net/hgz_gs/article/details/89848536 (注:本文就实际操作中遇到的小细节出现的问题做了略微修改,比如使用apt-get进行安装时需要先update更新)

 

1、发包工具

1.1 sendip

1.2 tcpreply

2、抓包工具

2.1、tcpdump

2.2 tcpflow

3、速率测试工具

4、加密工具

4.1 tcpcryptd

5.linux网络编程

5.1、tcp

5.2、udp


1、发包工具

1.1 sendip

Sendip是一个linux平台的命令行发数据包工具,目前(2018年2月)支持的协议有ipv4、ipv6、icmp、tcp、udp、bgp、rip、ntp。

安装:

sudo apt-get update

sudo apt-get install sendip

源码下载地址:

https://github.com/rickettm/SendIP

 简单使用:

(举例:

1、发送ICMPv4报文,-p icmp 将默认发送ICMP echo request报文,-v选项可在终端打印发送的报文

sendip -v -p ipv4 -is 192.168.2.129 -id 192.168.2.1 -p icmp -d 0xcafecafecafe 192.168.2.1

-v:打印发送报文内容

-p:协议(支持ipv4/ipv6/icmp/tcp/udp/...)

-is:源ip

-id:目的Ip

-d:携带的内容

 

2、发送TCP报文

sendip -v -p ipv4 -is 20.1.1.20 -id 20.1.1.21 -p tcp -ts 1024 -td 1024 -d 0xcafecafecafeabcdef 20.1.1.21

-ts:源端口

-td:目的端口

在目的端抓包查看该报文:tcpdump host 20.1.1.20 -nei ens160

05:28:54.673093 00:50:56:a6:79:73 > 00:50:56:a6:40:3e, ethertype 802.1Q (0x8100), length 64: vlan 520, p 0, ethertype IPv4, 20.1.1.20.200 > 20.1.1.21.300: Flags [S], seq 2250301441:2250301447, win 65535, length 6

 

 

3、发送IPv4 UDP报文,发送TCP只需把udp替换为tcp即可

sendip -v -p ipv4 -is 20.1.1.20 -id 20.1.1.21 -p udp -us 200 -ud 300 -d 0xcafecafecafe 20.1.1.21

 

抓包:

05:32:30.514950 00:50:56:a6:79:73 > 00:50:56:a6:40:3e, ethertype 802.1Q (0x8100), length 64: vlan 520, p 0, ethertype IPv4, 20.1.1.20.200 > 20.1.1.21.300: UDP, length 6

 

4、发送IPv6 UDP报文,同样发送TCP仅需把udp替换为tcp

sendip -p ipv6 -6s 2::3 -p udp -d 0xcafe 2::1

 

通用选项:

 
  1. -d 要携带的数据。rN随机产生N个字节,0x之后带十六进制,0之后带8进制。

  2. -f 从文件中读取要携带的数据。

  3. -p 加载协议模块,只有加载了才能使用。

  4. -v 打印整个发出的包。

ipv4模块:

 
  1. -iv x 版本 Default: 4

  2. -ih x 首部长度 Default: Correct

  3. -iy x 区分服务 Default: 0

  4. -il x 总长度 Default: Correct

  5. ----------------------------------------------32bit

  6. -ii x 标识 Default: Random

  7. -ifr x 标志 Default: 0 (options are 0,1,r)

  8. -if x 片偏移 Default: 0

  9. ----------------------------------------------32bit

  10. -it x 生存时间 Default: 255

  11. -ip x 协议 Default: 0, or set by underlying protocol

  12. -ic x 首部检验和 Default: Correct

  13. ----------------------------------------------32bit

  14. -is x 源地址 Default: 127.0.0.1

  15. ----------------------------------------------32bit

  16. -id x 目的地址 Default: Correct

  17. ----------------------------------------------32bit

  18. 下面全是可选字段(比较少用,不译):

  19.  
  20. -ifd x IP don't fragment flag (see README)

  21. Default: 0 (options are 0,1,r)

  22. -ifm x IP more fragments flag (see README)

  23. Default: 0 (options are 0,1,r)

  24. -ionum x

  25. IP option as string of hex bytes (length is always correct)

  26. Default: (no options)

  27. -ioeol IP option: end of list

  28. -ionop IP option: no-op

  29. -iorr x

  30. IP option: record route. Format: pointer:addr1:addr2:...

  31. -iots x

  32. IP option: timestamp. Format: pointer:overflow:flag:(ip1:)ts1:(ip2:)ts2:...

  33. -iolsr x

  34. IP option: loose source route. Format: pointer:addr1:addr2:...

  35. -iosid x

  36. IP option: stream identifier

  37. -iossr x

  38. IP option: strict source route. Format: pointer:addr1:addr2:...

tcp模块:

 
  1. -ts x 源端口 Default: 0

  2. -td x 目的端口 Default: 0

  3. ----------------------------------------------32bit

  4. -tn x 序号 Default: Random

  5. ----------------------------------------------32bit

  6. -ta x 确认号 Default: 0

  7. ----------------------------------------------32bit

  8. -tt x 数据偏移 Default: Correct

  9. -tr x 保留(ECN、CWR看rfc2481) Default: 0

  10. -tfu x URG Default: 0, or 1 if -tu specified (options are 0,1,r)

  11. -tfa x ACK Default: 0, or 1 if -ta specified (options are 0,1,r)

  12. -tfp x PSH Default: 0 (options are 0,1,r)

  13. -tfr x RST Default: 0 (options are 0,1,r)

  14. -tfs x SYN Default: 1 (options are 0,1,r)

  15. -tff x FIN Default: 0 (options are 0,1,r)

  16. -tw x 窗口 Default: 65535

  17. ----------------------------------------------32bit

  18. -tc x 检验和 Default: Correct

  19. -tu x 紧急指针 Default: 0

  20. ----------------------------------------------32bit

  21. 下面全是可选字段(比较少用,不译):

  22. -tonum x TCP option as string of hex bytes (length is always correct)

  23. Default: (no options)

  24. -toeol TCP option: end of list

  25. -tonop TCP option: no op

  26. -tomss x

  27. TCP option: maximum segment size

  28. -towscale x

  29. TCP option: window scale (rfc1323)

  30. -tosackok

  31. TCP option: allow selective ack (rfc2018)

  32. -tosack x

  33. TCP option: selective ack (rfc2018), format is l_edge1:r_edge1,l_edge2:r_edge2...

  34. -tots x

  35. TCP option: timestamp (rfc1323), format is tsval:tsecr

udp模块:

 
  1. -us x 源端口 Default: 0

  2. -ud x 目的端口 Default: 0

  3. -ul x 长度 Default: Correct

  4. -uc x 检验和 Default: Correct

要注意,按照从左到右的顺序依次封装报文,所以ip报文必须写在其他报文之前。如果协议中需要检验和之类的就按默认的就行了,省去计算的痛苦。下面有几个例子:

1、发送ICMPv4报文,-p icmp 将默认发送ICMP echo request报文,-v选项可在终端打印发送的报文

sendip -v -p ipv4 -is 192.168.2.129 -id 192.168.2.1 -p icmp -d 0xcafecafecafe 192.168.2.1


2、发送ICMPv6报文

sendip -p ipv6 -6s 2::3 -p icmp -d 0xcafecafecafe 2::1


3、发送IPv4 UDP报文,发送TCP只需把udp替换为tcp即可

sendip -p ipv4 -is 192.168.2.129 -p udp -d 0xcafe 192.168.2.1


4、发送IPv6 UDP报文,同样发送TCP仅需把udp替换为tcp

sendip -p ipv6 -6s 2::3 -p udp -d 0xcafe 2::1

5、将 test文件内容发送到udp端口

sendip -v -p ipv4 -id 14.215.177.39 -p udp -f test www.baidu.com

sendip -p ipv4 -is 192.168.1.2 -id 192.168.1.1 -p icmp -d 0x89ABCDEF www.google.com
 

其中主要的结构是sendip 网络层 上一层 数据 domain,domain是目的主机,可以是www.baidu.com192.168.1.1之类的。如果出现什么错误就会打印出帮助信息,里面有一行是提示错误原因,别漏看了。至于能不能发不规则的包(如数据与报文长度不符合、校验和乱写之类的),实际会不会发出去就没进行测试了。

1.2 tcpreply

tcpreplay是一种pcap包的重放工具, 它可以将用ethreal, wireshark工具抓下来的包原样或经过任意修改后重放回去. 它允许你对报文做任意的修改(主要是指对2层, 3层, 4层报文头), 指定重放报文的速度等, 这样tcpreplay就可以用来复现抓包的情景以定位bug, 以极快的速度重放从而实现压力测试。

安装使用方法参考:

https://blog.csdn.net/zhaomax/article/details/82773381

2、抓包工具

2.1、tcpdump

tcpdump :tcpdump可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。

ubuntu安装方法:

sudo apt-get install tcpdump

源码下载地址:

http://www.tcpdump.org/

嵌入式移植参考方法:

https://www.cnblogs.com/baiduboy/p/6243450.html

 使用语法:

在Linux操作系统中,必须使用系统管理员权限方能执行。

tcpdump [-adeflnNOpqStvx][-c<数据包数目>][-dd][-ddd][-F<表达文件>][-i<网络界面>][-r<数据包文件>][-s<数据包大小>][-tt][-T<数据包类型>][-vv][-w<数据包文件>][输出数据栏位]

参数说明

  • -a 尝试将网络和广播地址转换成名称。
  • -c<数据包数目> 收到指定的数据包数目后,就停止进行倾倒操作。
  • -d 把编译过的数据包编码转换成可阅读的格式,并倾倒到标准输出。
  • -dd 把编译过的数据包编码转换成C语言的格式,并倾倒到标准输出。
  • -ddd 把编译过的数据包编码转换成十进制数字的格式,并倾倒到标准输出。
  • -e 在每列倾倒资料上显示连接层级的文件头。
  • -f 用数字显示网际网络地址。
  • -F<表达文件> 指定内含表达方式的文件。
  • -i<网络界面> 使用指定的网络截面送出数据包。
  • -l 使用标准输出列的缓冲区。
  • -n 不把主机的网络地址转换成名字。
  • -N 不列出域名。
  • -O 不将数据包编码最佳化。
  • -p 不让网络界面进入混杂模式。
  • -q 快速输出,仅列出少数的传输协议信息。
  • -r<数据包文件> 从指定的文件读取数据包数据。
  • -s<数据包大小> 设置每个数据包的大小。
  • -S 用绝对而非相对数值列出TCP关联数。
  • -t 在每列倾倒资料上不显示时间戳记。
  • -tt 在每列倾倒资料上显示未经格式化的时间戳记。
  • -T<数据包类型> 强制将表达方式所指定的数据包转译成设置的数据包类型。
  • -v 详细显示指令执行过程。
  • -vv 更详细显示指令执行过程。
  • -x 用十六进制字码列出数据包资料。
  • -w<数据包文件> 把数据包数据写入指定的文件。

使用例子:

1. tcpdump -D 获取网络适配器列表,以下是在Ubuntu上获取到的结果:

hegaozhi@ubuntu:~$ tcpdump -D
1.ens33 [Up, Running]
2.any (Pseudo-device that captures on all interfaces) [Up, Running]
3.lo [Up, Running, Loopback]
4.bluetooth0 (Bluetooth adapter number 0)
5.nflog (Linux netfilter log (NFLOG) interface)
6.nfqueue (Linux netfilter queue (NFQUEUE) interface)
7.usbmon1 (USB bus number 1)
8.usbmon2 (USB bus number 2)
9.usbmon3 (USB bus number 3)
10.usbmon4 (USB bus number 4)

2. tcpdump -i <需要监控的网络适配器编号>,例如监控网卡ens33 ,则使用tcpdump -i 1。 

hegaozhi@ubuntu:~$ sudo tcpdump -i 1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes

3. 使用无线网卡ens33 监控IP地址为172.16.86.111上443端口的tcp协议:

sudo tcpdump -i 1 host 172.16.86.111 and tcp port 443

4. 使用无线网卡ens33 监控IP地址为172.16.86.111上8308端口的udp协议:

sudo tcpdump -i 1 host 172.16.86.111 and udp port 8308

5. 如果想要显示数据包的内容,需要使用-X参数,如,我想要显示捕获的https数据包http header的内容:

sudo tcpdump -X -i 1 host 172.16.86.111 and tcp port 443

    可以看到该结果只显示了https头的一部分,没有显示全,是因为tcpdump默认将显示的数据长度截断了,可以使用-s后面加数据长度,来设置数据显示长度:

sudo tcpdump -X -s 0 -i 1 host 172.16.86.111 and tcp port 443

以上的例子中,-s 0 表示自动设置长度使其能够显示所有数据。

  6. 使用-w参数将捕获的数据存储为.cap文件:

sudo tcpdump -X -s 0 -i 1 -w tcplog.cap host 192.9.200.59 and tcp port 8000

使用-r参数查看.cap 文件:

sudo tcpdump -X -s 0 -i 1 -r tcplog.cap host 172.16.86.111 and tcp port 443

7. 抓192.168.1.123的80端口和110和25以外的其他端口的包 

sudo tcpdump -i eth1 host 192.168.1.123 and ! port 80 and ! port 25 and ! port 110 -w /tmp/xxx.cap

8.抓pppoe的密码 

sudo tcpdump -i eth1 pppoes -w /tmp/xxx.cap

9.后台抓包, 控制台退出也不会影响: 

sudo  nohup tcpdump -i eth1 port 110 -w /tmp/xxx.cap & 

10.以100m大小分割保存文件, 超过100m另开一个文件 -C 100m 

sudo tcpdump -i eth1 pppoes -w /tmp/xxx.cap -C 100m 

11.抓10000个包后退出 -c 10000 

sudo tcpdump -i eth1 pppoes -w /tmp/xxx.cap -c 10000 

 

抓下来的.cap文件可以直接用ethereal 或者wireshark打开。

2.2 tcpflow

tcpflow实际上也是一个抓包工具,tcpflow与tcpdump不同的是它是以流为单位显示数据内容,而tcpdump以包为单位显示数据。分析HTTP数据,使用tcpflow会更便捷。

#截取本机(192.168.31.147)和主机114.114.114.114之间的数据
tcpdump -n -i eth0 host 192.168.31.147 and 114.114.114.114
#截取全部进入服务器的数据可以使用以下的格式
tcpdump -n -i eth0 dst 192.168.31.147
#服务器有多个IP 可以使用参数
tcpdump -n -i eth0 dst 192.168.31.147  or  192.168.31.157
#从本机出去的数据包
tcpdump -n -i eth0 src 192.168.31.147 or 192.168.31.157

-C:在将一个原始数据包写入一个保存文件之前,请检查该文件是否大于 file_size ,如果是,关闭当前的保存文件并打开一个新文件。第一个保存文件后的保存文件将具有用-w 标志指定的名称 ,后面跟着一个数字,从1开始并继续向上。file_size的单位 是数百万字节(1,000,000字节,而不是1,048,576字节)。

-w:将原始数据包写入 文件, 而不是解析并打印出来。他们以后可以用-r选项打印。如果文件 是“ - ”,则使用标准输出。

-W:与-C 选项一起使用时 ,这会将创建的文件数量限制为指定的数字,并从头开始覆盖文件,从而创建“旋转”缓冲区。另外,它将命名带有足够前导0的文件来支持最大数量的文件,使它们能够正确排序。与-G 选项一起使用时 ,这将限制创建的旋转转储文件的数量,在达到限制时以状态0退出。如果与-C一起使用 ,则行为将导致每个时间片的循环文件

 

3、速率测试工具

  ping命令是一条最基础的测试本机到目的ip连通性的工具,如下图,不带任何参数的ping命令默认每秒发送一个数据包,并返回结果,按下CTRL+C结束,而如果使用-f参数则可以快速不断发送icmp数据包,可以通过-f参数查看大概的丢包率 ping命令返回结果中可以看到总共发送了多少个包,有多少个包被成功接收,丢包率是多少,ping的总共时长是多少等等

【工具】ubuntu16安装sendip发包工具,模拟发送tcp/udp/icmp报文_第1张图片

Linux下ping大数据包的格式;

语  法:ping [-aAbBdDfhLnOqrRUvV] [-I 本地网卡名或者IP地址] [-c<完成次数>][-i<间隔秒数>][-l<指定数量的信息包>][-p<设置icmp报文数据的内容>][-s<数据包大小单位字节(B),>][-t<存活数值>] [-w 指定等待的超时时间] [-W 超时时间]  [主机名称或IP地址]

 

4、加密工具

4.1 tcpcryptd

5.linux网络编程

5.1、tcp

服务器server.c代码:

 
  1. #include

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include

  8. #include

  9. #include

  10. #include

  11. #include

  12. #include

  13. #include

  14. #include

  15.  
  16. #define MAXLINE 256

  17. #define PORT 6666

  18. int listenfd;

  19. int connfd;

  20. pthread_t read_id, write_id;

  21.  
  22. /*

  23. linux ctrl + C 会产生 SIGINT信号

  24. 接收到SIGINT 信号进入该函数

  25. */

  26. void stop(int signo)

  27. {

  28. printf("stop\n");

  29. close(connfd);

  30. close(listenfd);

  31. _exit(0);

  32. }

  33.  
  34. /*

  35. 当客户端断开连接的时候,

  36. 在服务端socket send进程可以收到收到信号SIGPIPE,

  37. 收到SIGPIPE信号进入该函数结束创建的线程。

  38. */

  39. void signal_pipe(int signo)

  40. {

  41. pthread_kill(read_id,SIGQUIT);//向read线程发送SIGQUIT

  42. pthread_join(read_id,NULL); //阻塞线程运行,直到read 线程退出。

  43.  
  44. close(connfd); //关闭连接

  45. printf("read pthread out \n");

  46.  
  47. pthread_exit(0); //结束write 线程

  48. }

  49.  
  50. /*

  51. read 线程接收到SIGQUIT信号,

  52. 执行线程退出操作

  53. */

  54. void pthread_out(int signo)

  55. {

  56. pthread_exit(0);

  57. }

  58.  
  59. /*

  60. read 线程执行函数

  61. */

  62. void* read_func(void* arg)

  63. {

  64. char readbuff[MAXLINE];

  65. int n = 0;

  66. int fd;

  67.  
  68. fd = *(int*)arg; /*main 主进程传递过来的连接文件描述符*/

  69. memset(&readbuff,0,sizeof(readbuff));

  70.  
  71. signal(SIGQUIT,pthread_out); /* 注册SIGQUIT 信号*/

  72. while(1)

  73. {

  74. n = recv(fd, readbuff, MAXLINE, 0); /*recv 在这里是阻塞运行*/

  75. if(n > 0)

  76. {

  77. printf("server recv data: %s \n",readbuff);

  78. }

  79. };

  80. }

  81. /*

  82. write 线程执行函数

  83. */

  84. void* write_func(void* arg)

  85. {

  86. char writebuff[MAXLINE];

  87. char* write = "I am server";

  88. unsigned char i = 0;

  89. int num = 0;

  90. int fd;

  91.  
  92. fd = *(int*)arg;

  93. memset(&writebuff,0,sizeof(writebuff));

  94.  
  95. signal(SIGPIPE,signal_pipe); /* 注册 SIGPIPE信号 */

  96. while(1)

  97. {

  98. sleep(1);

  99. send(fd,write,strlen(write)+1,0);/*向客户端发送数据*/

  100. }

  101. }

  102.  
  103. int main(int argc, char** argv)

  104. {

  105. char buff[MAXLINE];

  106. int num;

  107. int addrlen;

  108. struct sockaddr_in server_addr; /*服务器地址结构*/

  109. struct sockaddr_in client_addr; /*客户端地址结构*/

  110.  
  111. if((listenfd = socket(AF_INET,SOCK_STREAM,0)) == -1)/*建立一个流式套接字*/

  112. {

  113. printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);

  114. exit(0);

  115. }

  116.  
  117. /*设置服务端地址*/

  118. addrlen = sizeof(struct sockaddr_in);

  119. memset(&server_addr, 0, addrlen);

  120. server_addr.sin_family = AF_INET; /*AF_INET表示 IPv4 Intern 协议*/

  121. server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*INADDR_ANY 可以监听任意IP */

  122. server_addr.sin_port = htons(PORT); /*设置端口*/

  123.  
  124. /*绑定地址结构到套接字描述符*/

  125. if( bind(listenfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)

  126. {

  127. printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);

  128. exit(0);

  129. }

  130.  
  131. /*设置监听队列,这里设置为1,表示只能同时处理一个客户端的连接*/

  132. if( listen(listenfd, 1) == -1)

  133. {

  134. printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);

  135. exit(0);

  136. }

  137.  
  138. signal(SIGINT,stop); /*注册SIGINT 信号*/

  139. while(1)

  140. {

  141. printf("wait client accpt \n");

  142. if( (connfd = accept(listenfd, (struct sockaddr*)&client_addr, &addrlen)) == -1)/*接收客户端的连接,这里会阻塞,直到有客户端连接*/

  143. {

  144. printf("accept socket error: %s(errno: %d)",strerror(errno),errno);

  145. continue;

  146. }

  147.  
  148. if(pthread_create(&read_id,NULL,read_func,&connfd))/*创建 read 线程*/

  149. {

  150. printf("pthread_create read_func err\n");

  151. }

  152.  
  153. if(pthread_create(&write_id,NULL,write_func,&connfd))/*创建 write 线程*/

  154. {

  155. printf("pthread_create write_func err\n");

  156. }

  157.  
  158. pthread_join(write_id,NULL); /*阻塞,直到write进程退出后才进行新的客户端连接*/

  159. printf("write pthread out \n");

  160. }

  161. }

客户端client.c代码:

 
  1. #include

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include

  8. #include

  9. #include

  10. #include

  11. #include

  12. #include

  13. #include

  14. #include

  15.  
  16. #define MAXLINE 256

  17. #define PORT 6666

  18. int fd;

  19. /*

  20. linux ctrl + C 会产生 SIGINT信号

  21. 接收到SIGINT 信号进入该函数

  22. */

  23. void stop(int signo)

  24. {

  25. printf("client stop\n");

  26. close(fd);

  27. _exit(0);

  28. }

  29.  
  30. /*客户端处理函数*/

  31. void client_process(void)

  32. {

  33. char readbuff[MAXLINE];

  34. char writebuff[MAXLINE];

  35. char * write = "I am client";

  36. int num = 0;

  37.  
  38. while(1)

  39. {

  40. num = recv(fd,readbuff,MAXLINE,0);/*接收服务端的数据,recv在这里如果没有数据会阻塞*/

  41. if(num > 0)

  42. {

  43. printf("client read data : %s \n",readbuff);

  44. send(fd, write, strlen(write)+1, 0); /*接收到数据后再向服务端发送一个字符串*/

  45. }

  46. else if(num == 0)/*recv返回值为0 的时候表示服务端已经断开了连接*/

  47. {

  48. stop(1); /*执行退出操作*/

  49. }

  50. }

  51. }

  52.  
  53. int main(int argc, char** argv)

  54. {

  55. struct sockaddr_in server_addr;

  56. struct sockaddr_in client_addr;

  57. int ret;

  58.  
  59. fd = socket(AF_INET,SOCK_STREAM,0);/*建立流式套接字*/

  60. if(fd < 0)

  61. {

  62. printf("clinet socket err \n");

  63. }

  64.  
  65. /*设置服务端地址*/

  66. memset(&server_addr,0,sizeof(server_addr));

  67. server_addr.sin_family = AF_INET; /*AF_INET表示 IPv4 Intern 协议*/

  68. server_addr.sin_addr.s_addr = htonl(INADDR_ANY);/*INADDR_ANY 可以监听任意IP */

  69. server_addr.sin_port = htons(PORT); /*设置端口*/

  70.  
  71. inet_pton(AF_INET,argv[1],&server_addr.sin_addr);/*将用户输入的字符串类型的IP地址转为整型*/

  72. connect(fd,(struct sockaddr*)&server_addr,sizeof(server_addr));/*连接服务器*/

  73.  
  74. signal(SIGINT,stop); /*注册SIGINT信号*/

  75. client_process(); /*进入处理函数*/

  76.  
  77. close(fd);/*关闭文件*/

  78. return 0;

  79. }

Makefile:

 
  1. CC = gcc

  2. CPP = g++

  3. RM = rm -rf

  4.  
  5. ## debug flag

  6. DBG_ENABLE = 1

  7.  
  8. ## source file path

  9. SRC_PATH := .

  10.  
  11. ## get all source files

  12. SRCS += $(wildcard $(SRC_PATH)/*.c)

  13.  
  14. ## target exec file name

  15. TARGET := $(SRCS:.c=)

  16.  
  17. ## all .o based on all .c

  18. OBJS := $(SRCS:.c=.o)

  19.  
  20.  
  21. ## need libs, add at here

  22. LIBS := pthread

  23.  
  24. ## used headers file path

  25. INCLUDE_PATH := .

  26.  
  27. ## used include librarys file path

  28. LIBRARY_PATH := /lib

  29.  
  30. ## debug for debug info, when use gdb to debug

  31. ifeq (1, ${DBG_ENABLE})

  32. CFLAGS += -D_DEBUG -O0 -g -DDEBUG=1

  33. endif

  34.  
  35. ## get all include path

  36. CFLAGS += $(foreach dir, $(INCLUDE_PATH), -I$(dir))

  37.  
  38. ## get all library path

  39. LDFLAGS += $(foreach lib, $(LIBRARY_PATH), -L$(lib))

  40.  
  41. ## get all librarys

  42. LDFLAGS += $(foreach lib, $(LIBS), -l$(lib))

  43.  
  44.  
  45. all: clean build $(TARGET)

  46.  
  47. build:

  48. gcc client.c -o client -lpthread

  49. gcc server.c -o server -lpthread

  50.  
  51. clean:

  52. $(RM) $(OBJS) $(TARGET)

 编译:

hegaozhi@ubuntu:~/tcp$ make

 运行:

先运行服务器:

./server

 新建终端运行客户端,其中127.0.0.1为服务器的ip地址:

./client 127.0.0.1

5.2、udp

客户端service.cpp代码:

 
  1. #include

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include

  8. #include

  9.  
  10. #define MYPORT 8308

  11.  
  12.  
  13. #define ERR_EXIT(m) \

  14. do { \

  15. perror(m); \

  16. exit(EXIT_FAILURE); \

  17. } while (0)

  18.  
  19. void echo_ser(int sock)

  20. {

  21. char recvbuf[1024] = {0};

  22. struct sockaddr_in peeraddr;

  23. socklen_t peerlen;

  24. int n;

  25.  
  26. while (1)

  27. {

  28.  
  29. peerlen = sizeof(peeraddr);

  30. memset(recvbuf, 0, sizeof(recvbuf));

  31. n = recvfrom(sock, recvbuf, sizeof(recvbuf), 0,

  32. (struct sockaddr *)&peeraddr, &peerlen);

  33. if (n <= 0)

  34. {

  35.  
  36. if (errno == EINTR)

  37. continue;

  38.  
  39. ERR_EXIT("recvfrom error");

  40. }

  41. else if(n > 0)

  42. {

  43. printf("接收到的数据:%s\n",recvbuf);

  44. sendto(sock, recvbuf, n, 0,

  45. (struct sockaddr *)&peeraddr, peerlen);

  46. printf("回送的数据:%s\n",recvbuf);

  47. }

  48. }

  49. close(sock);

  50. }

  51.  
  52. int main(void)

  53. {

  54. int sock;

  55. if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)

  56. ERR_EXIT("socket error");

  57.  
  58. struct sockaddr_in servaddr;

  59. memset(&servaddr, 0, sizeof(servaddr));

  60. servaddr.sin_family = AF_INET;

  61. servaddr.sin_port = htons(MYPORT);

  62. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

  63.  
  64. printf("监听%d端口\n",MYPORT);

  65. if (bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)

  66. ERR_EXIT("bind error");

  67.  
  68. echo_ser(sock);

  69.  
  70. return 0;

  71. }

  72.  

客户端client.cpp代码:

 
  1. #include

  2. #include

  3. #include

  4. #include

  5. #include

  6. #include

  7. #include

  8. #include

  9. #include

  10.  
  11. #define MYPORT 8308

  12. char* SERVERIP = "127.0.0.1";

  13.  
  14. #define ERR_EXIT(m) \

  15. do \

  16. { \

  17. perror(m); \

  18. exit(EXIT_FAILURE); \

  19. } while(0)

  20.  
  21. void echo_cli(int sock)

  22. {

  23. struct sockaddr_in servaddr;

  24. memset(&servaddr, 0, sizeof(servaddr));

  25. servaddr.sin_family = AF_INET;

  26. servaddr.sin_port = htons(MYPORT);

  27. //servaddr.sin_addr.s_addr = inet_addr(SERVERIP);

  28. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

  29.  
  30. int ret;

  31. char sendbuf[1024] = {0};

  32. char recvbuf[1024] = {0};

  33. while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)

  34. {

  35.  
  36. printf("向服务器发送:%s\n",sendbuf);

  37. sendto(sock, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

  38.  
  39. ret = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, NULL, NULL);

  40. if (ret == -1)

  41. {

  42. if (errno == EINTR)

  43. continue;

  44. ERR_EXIT("recvfrom");

  45. }

  46. printf("从服务器接收:%s\n",recvbuf);

  47.  
  48. memset(sendbuf, 0, sizeof(sendbuf));

  49. memset(recvbuf, 0, sizeof(recvbuf));

  50. }

  51.  
  52. close(sock);

  53.  
  54.  
  55. }

  56.  
  57. int main(void)

  58. {

  59. int sock;

  60. if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)

  61. ERR_EXIT("socket");

  62.  
  63. echo_cli(sock);

  64.  
  65. return 0;

  66. }

  67.  

Makefile文件内容:

 
  1. CC = gcc

  2. CPP = g++

  3. RM = rm -rf

  4.  
  5. ## debug flag

  6. DBG_ENABLE = 1

  7.  
  8. ## source file path

  9. SRC_PATH := .

  10.  
  11. ## get all source files

  12. SRCS += $(wildcard $(SRC_PATH)/*.cpp)

  13.  
  14. ## target exec file name

  15. TARGET := $(SRCS:.cpp=)

  16.  
  17. ## all .o based on all .cpp

  18. OBJS := $(SRCS:.cpp=.o)

  19.  
  20.  
  21. ## need libs, add at here

  22. LIBS := pthread

  23.  
  24. ## used headers file path

  25. INCLUDE_PATH := .

  26.  
  27. ## used include librarys file path

  28. LIBRARY_PATH := /lib

  29.  
  30. ## debug for debug info, when use gdb to debug

  31. ifeq (1, ${DBG_ENABLE})

  32. CFLAGS += -D_DEBUG -O0 -g -DDEBUG=1

  33. endif

  34.  
  35. ## get all include path

  36. CFLAGS += $(foreach dir, $(INCLUDE_PATH), -I$(dir))

  37.  
  38. ## get all library path

  39. LDFLAGS += $(foreach lib, $(LIBRARY_PATH), -L$(lib))

  40.  
  41. ## get all librarys

  42. LDFLAGS += $(foreach lib, $(LIBS), -l$(lib))

  43.  
  44.  
  45. all: clean build $(TARGET)

  46.  
  47. build:

  48. g++ client.cpp -o client -lpthread

  49. g++ service.cpp -o service -lpthread

  50.  
  51. clean:

  52. $(RM) $(OBJS) $(TARGET)

运行:

先运行服务器:

hegaozhi@ubuntu:~/test/socket/udp$ ./service
监听2368端口
Velodyne socket fd is 3

新建终端运行客户端,并输入hello:

hegaozhi@ubuntu:~/test/socket/udp$ ./client
hello
向服务器发送:hello

6. 局域网在线IP探测

用nmap对局域网扫描一遍,然后查看arp缓存表就可以知道局域内ip对应的mac了。nmap比较强大也可以直接扫描mac地址和端口。执行扫描之后就可以 cat /proc/net/arp查看arp缓存表了。

             进行ping扫描,打印出对扫描做出响应的主机:  

$ nmap -sP 192.168.1.0/24  

仅列出指定网络上的每台主机,不发送任何报文到目标主机: 

$ nmap -sL 192.168.1.0/24 

探测目标主机开放的端口,可以指定一个以逗号分隔的端口列表(如-PS 22,23,25,80):  

$ nmap -PS 192.168.1.234  

使用UDP ping探测主机:

$ nmap -PU 192.168.1.0/24  

使用频率最高的扫描选项(SYN扫描,又称为半开放扫描),它不打开一个完全的TCP连接,执行得很快: 

$ nmap -sS 192.168.1.0/24

 

你可能感兴趣的:(linux,linux,ubuntu)