linux 网络抓包_Stream抓包软件[通俗易懂]

linux 网络抓包_Stream抓包软件[通俗易懂]目录1、发包工具1.1sendip1.2tcpreply2、抓包工具2.1、tcpdump2.2tcpflow3、速率测试工具4、加密工具4.1tcpcryptd5.linux网络编程5.1

linux

目录

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。

ubuntu安装:

sudo apt-get install sendip

源码下载地址:

https://github.com/rickettm/SendIP

 简单使用:

通用选项:

-d    要携带的数据。rN随机产生N个字节,0x之后带十六进制,0之后带8进制。
-f    从文件中读取要携带的数据。
-p    加载协议模块,只有加载了才能使用。
-v    打印整个发出的包。

ipv4模块:

-iv x      版本               Default: 4
-ih x      首部长度       Default: Correct
-iy x      区分服务       Default: 0
-il x      总长度           Default: Correct
----------------------------------------------32bit
-ii x      标识               Default: Random
-ifr x     标志               Default: 0 (options are 0,1,r)
-if x      片偏移           Default: 0
----------------------------------------------32bit
-it x      生存时间       Default: 255
-ip x      协议             Default: 0, or set by underlying protocol
-ic x      首部检验和   Default: Correct
----------------------------------------------32bit
-is x      源地址          Default: 127.0.0.1
----------------------------------------------32bit
-id x      目的地址      Default: Correct
----------------------------------------------32bit
下面全是可选字段(比较少用,不译):

-ifd x IP don't fragment flag (see README)
       Default: 0 (options are 0,1,r)
-ifm x IP more fragments flag (see README)
       Default: 0 (options are 0,1,r)
-ionum x
       IP option as string of hex bytes (length is always correct)
       Default: (no options)
-ioeol IP option: end of list
-ionop IP option: no-op
-iorr x
       IP option: record route. Format: pointer:addr1:addr2:...
-iots x
       IP option: timestamp. Format: pointer:overflow:flag:(ip1:)ts1:(ip2:)ts2:...
-iolsr x
       IP option: loose source route. Format: pointer:addr1:addr2:...
-iosid x
       IP option: stream identifier
-iossr x
       IP option: strict source route. Format: pointer:addr1:addr2:...

tcp模块:

-ts x  源端口       Default: 0
-td x  目的端口       Default: 0
----------------------------------------------32bit
-tn x  序号       Default: Random
----------------------------------------------32bit
-ta x  确认号       Default: 0
----------------------------------------------32bit
-tt x  数据偏移       Default: Correct
-tr x  保留(ECN、CWR看rfc2481)       Default: 0
-tfu x URG       Default: 0, or 1 if -tu specified (options are 0,1,r)
-tfa x ACK       Default: 0, or 1 if -ta specified (options are 0,1,r)
-tfp x PSH       Default: 0 (options are 0,1,r)
-tfr x RST       Default: 0 (options are 0,1,r)
-tfs x SYN       Default: 1 (options are 0,1,r)
-tff x FIN       Default: 0 (options are 0,1,r)
-tw x  窗口       Default: 65535
----------------------------------------------32bit
-tc x  检验和       Default: Correct
-tu x  紧急指针       Default: 0
----------------------------------------------32bit
下面全是可选字段(比较少用,不译):
-tonum x       TCP option as string of hex bytes (length is always correct)
       Default: (no options)
-toeol TCP option: end of list
-tonop TCP option: no op
-tomss x
       TCP option: maximum segment size
-towscale x
       TCP option: window scale (rfc1323)
-tosackok
       TCP option: allow selective ack (rfc2018)
-tosack x
       TCP option: selective ack (rfc2018), format is l_edge1:r_edge1,l_edge2:r_edge2...
-tots x
       TCP option: timestamp (rfc1323), format is tsval:tsecr

udp模块:

-us x  源端口    Default: 0
-ud x  目的端口    Default: 0
-ul x 长度    Default: Correct
-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, 以极快的速度重放从而实现压力测试。

安装使用方法参考:

tcpreplay的安装使用_zhaomax的博客-CSDN博客_tcpreplay

2、抓包工具

2.1、tcpdump

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

ubuntu安装方法:

sudo apt-get install tcpdump

源码下载地址:

Home | TCPDUMP & LIBPCAP

嵌入式移植参考方法:

Linux中tcpdump的编译和使用 – _小百 – 博客园

 使用语法:

在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

可以添加 -tttt 选项使时间戳格式更加可读。

tcpdump -ttttnnr tcplog.cap

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的总共时长是多少等等

 

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代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<termios.h>
#include<sys/types.h>   
#include<sys/stat.h>    
#include<fcntl.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<signal.h>
 
#define MAXLINE 256
#define PORT	6666
int listenfd;
int connfd;
pthread_t read_id, write_id;
 
/*
linux ctrl + C 会产生 SIGINT信号
接收到SIGINT 信号进入该函数
*/
void stop(int signo)
{
	printf("stop\n");
	close(connfd);	
	close(listenfd);
	 _exit(0);
}
 
/*
当客户端断开连接的时候,
在服务端socket send进程可以收到收到信号SIGPIPE,
收到SIGPIPE信号进入该函数结束创建的线程。
*/
void signal_pipe(int signo)
{
	pthread_kill(read_id,SIGQUIT);//向read线程发送SIGQUIT
	pthread_join(read_id,NULL);	  //阻塞线程运行,直到read 线程退出。
	
	close(connfd);                //关闭连接
	printf("read pthread out \n");
	
	pthread_exit(0);              //结束write 线程
}
 
/*
read 线程接收到SIGQUIT信号,
执行线程退出操作
*/
void pthread_out(int signo)
{
	pthread_exit(0);
}
 
/*
read 线程执行函数
*/
void* read_func(void* arg)
{
	char readbuff[MAXLINE];
	int n = 0;
	int fd;
 
	fd = *(int*)arg;    /*main 主进程传递过来的连接文件描述符*/
	memset(&readbuff,0,sizeof(readbuff));
 
	signal(SIGQUIT,pthread_out); /* 注册SIGQUIT 信号*/ 
	while(1)
	{
    	n = recv(fd, readbuff, MAXLINE, 0);  /*recv 在这里是阻塞运行*/
		if(n > 0)
		{
			printf("server recv data: %s \n",readbuff);
		}
	};
}
/*
write 线程执行函数
*/
void* write_func(void* arg)
{
	char writebuff[MAXLINE];
	char* write = "I am server";
	unsigned char i = 0;
	int num = 0;
	int fd;
 
	fd = *(int*)arg;
	memset(&writebuff,0,sizeof(writebuff));
	
	signal(SIGPIPE,signal_pipe); /* 注册 SIGPIPE信号 */
	while(1)
	{
		sleep(1);
		send(fd,write,strlen(write)+1,0);/*向客户端发送数据*/
	}
}
 
int main(int argc, char** argv)
{
	char buff[MAXLINE];
	int num;
	int addrlen;
	struct sockaddr_in server_addr;  /*服务器地址结构*/
	struct sockaddr_in client_addr;  /*客户端地址结构*/
 
	if((listenfd = socket(AF_INET,SOCK_STREAM,0)) == -1)/*建立一个流式套接字*/
	{
		printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
		exit(0);
	}
	
	/*设置服务端地址*/
	addrlen = sizeof(struct sockaddr_in);
	memset(&server_addr, 0, addrlen);
	server_addr.sin_family = AF_INET;    /*AF_INET表示 IPv4 Intern 协议*/
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*INADDR_ANY 可以监听任意IP */
	server_addr.sin_port = htons(PORT); /*设置端口*/
    
	/*绑定地址结构到套接字描述符*/
	if( bind(listenfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
	{
		printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
		exit(0);
	}
 
	/*设置监听队列,这里设置为1,表示只能同时处理一个客户端的连接*/
	if( listen(listenfd, 1) == -1)
	{
		printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
		exit(0);
	}
	
	signal(SIGINT,stop); /*注册SIGINT 信号*/
	while(1)
	{	
		printf("wait client accpt \n");
		if( (connfd = accept(listenfd, (struct sockaddr*)&client_addr, &addrlen)) == -1)/*接收客户端的连接,这里会阻塞,直到有客户端连接*/
		{
			printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
			continue;
		}
	
		if(pthread_create(&read_id,NULL,read_func,&connfd))/*创建 read 线程*/
		{
			printf("pthread_create read_func err\n");
		}
 
		if(pthread_create(&write_id,NULL,write_func,&connfd))/*创建 write 线程*/
		{
			printf("pthread_create write_func err\n");
		}
		
		pthread_join(write_id,NULL); /*阻塞,直到write进程退出后才进行新的客户端连接*/
		printf("write pthread out \n");
	}
}

客户端client.c代码:

#include<stdio.h>       
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<termios.h>
#include<sys/types.h>   
#include<sys/stat.h>    
#include<fcntl.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<signal.h>
 
#define MAXLINE 256
#define PORT    6666
int fd;
/*
linux ctrl + C 会产生 SIGINT信号
接收到SIGINT 信号进入该函数
*/
void stop(int signo)
{
    printf("client stop\n");
	close(fd);  
	_exit(0);
}
 
/*客户端处理函数*/
void client_process(void)
{
	char readbuff[MAXLINE];
	char writebuff[MAXLINE];
	char * write = "I am client";
	int num = 0;
	
	while(1)
	{
		num = recv(fd,readbuff,MAXLINE,0);/*接收服务端的数据,recv在这里如果没有数据会阻塞*/
		if(num > 0)
		{
			printf("client read data : %s \n",readbuff);
			send(fd, write, strlen(write)+1, 0); /*接收到数据后再向服务端发送一个字符串*/
		}
		else if(num == 0)/*recv返回值为0 的时候表示服务端已经断开了连接*/
		{
			stop(1); /*执行退出操作*/
		}
	}
}
 
int main(int argc, char** argv)
{
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int ret;
 
	fd = socket(AF_INET,SOCK_STREAM,0);/*建立流式套接字*/
	if(fd < 0)
	{
		printf("clinet socket err \n");
	}
 
	/*设置服务端地址*/
	memset(&server_addr,0,sizeof(server_addr));
	server_addr.sin_family = AF_INET; 				/*AF_INET表示 IPv4 Intern 协议*/
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);/*INADDR_ANY 可以监听任意IP */
	server_addr.sin_port = htons(PORT);				/*设置端口*/
 
	inet_pton(AF_INET,argv[1],&server_addr.sin_addr);/*将用户输入的字符串类型的IP地址转为整型*/
	connect(fd,(struct sockaddr*)&server_addr,sizeof(server_addr));/*连接服务器*/
	
	signal(SIGINT,stop);	/*注册SIGINT信号*/
	client_process();		/*进入处理函数*/
	
	close(fd);/*关闭文件*/
	return 0;
}

Makefile:

CC      = gcc
CPP     = g++
RM      = rm -rf

## debug flag
DBG_ENABLE   = 1

## source file path
SRC_PATH   := .

## get all source files
SRCS         += $(wildcard $(SRC_PATH)/*.c)

## target exec file name
TARGET     := $(SRCS:.c=)

## all .o based on all .c
OBJS        := $(SRCS:.c=.o)


## need libs, add at here
LIBS := pthread

## used headers  file path
INCLUDE_PATH := .

## used include librarys file path
LIBRARY_PATH := /lib

## debug for debug info, when use gdb to debug
ifeq (1, ${DBG_ENABLE}) 
	CFLAGS += -D_DEBUG -O0 -g -DDEBUG=1
endif

## get all include path
CFLAGS  += $(foreach dir, $(INCLUDE_PATH), -I$(dir))

## get all library path
LDFLAGS += $(foreach lib, $(LIBRARY_PATH), -L$(lib))

## get all librarys
LDFLAGS += $(foreach lib, $(LIBS), -l$(lib))


all: clean build $(TARGET)

build:
	gcc client.c -o client -lpthread
	gcc server.c -o server -lpthread

clean:
	$(RM) $(OBJS) $(TARGET)

 编译:

hegaozhi@ubuntu:~/tcp$ make

 运行:

先运行服务器:

./server

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

./client 127.0.0.1

5.2、udp

客户端service.cpp代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
 
#define MYPORT 8308
 
 
#define ERR_EXIT(m) \
    do { \
    perror(m); \
    exit(EXIT_FAILURE); \
    } while (0)
 
void echo_ser(int sock)
{
    char recvbuf[1024] = {0};
    struct sockaddr_in peeraddr;
    socklen_t peerlen;
    int n;
    
    while (1)
    {
        
        peerlen = sizeof(peeraddr);
        memset(recvbuf, 0, sizeof(recvbuf));
        n = recvfrom(sock, recvbuf, sizeof(recvbuf), 0,
                     (struct sockaddr *)&peeraddr, &peerlen);
        if (n <= 0)
        {
            
            if (errno == EINTR)
                continue;
            
            ERR_EXIT("recvfrom error");
        }
        else if(n > 0)
        {
            printf("接收到的数据:%s\n",recvbuf);
            sendto(sock, recvbuf, n, 0,
                   (struct sockaddr *)&peeraddr, peerlen);
            printf("回送的数据:%s\n",recvbuf);
        }
    }
    close(sock);
}
 
int main(void)
{
    int sock;
    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
        ERR_EXIT("socket error");
    
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(MYPORT);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    printf("监听%d端口\n",MYPORT);
    if (bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        ERR_EXIT("bind error");
    
    echo_ser(sock);
    
    return 0;
}

客户端client.cpp代码:

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
 
#define MYPORT 8308
char* SERVERIP = "127.0.0.1";
 
#define ERR_EXIT(m) \
    do \
{ \
    perror(m); \
    exit(EXIT_FAILURE); \
    } while(0)
 
void echo_cli(int sock)
{
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(MYPORT);
    //servaddr.sin_addr.s_addr = inet_addr(SERVERIP);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    int ret;
    char sendbuf[1024] = {0};
    char recvbuf[1024] = {0};
    while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
    {
        
        printf("向服务器发送:%s\n",sendbuf);
        sendto(sock, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
        
        ret = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, NULL, NULL);
        if (ret == -1)
        {
            if (errno == EINTR)
                continue;
            ERR_EXIT("recvfrom");
        }
        printf("从服务器接收:%s\n",recvbuf);
        
        memset(sendbuf, 0, sizeof(sendbuf));
        memset(recvbuf, 0, sizeof(recvbuf));
    }
    
    close(sock);
    
    
}
 
int main(void)
{
    int sock;
    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
        ERR_EXIT("socket");
    
    echo_cli(sock);
    
    return 0;
}

Makefile文件内容:

CC      = gcc
CPP     = g++
RM      = rm -rf

## debug flag
DBG_ENABLE   = 1

## source file path
SRC_PATH   := .

## get all source files
SRCS         += $(wildcard $(SRC_PATH)/*.cpp)

## target exec file name
TARGET     := $(SRCS:.cpp=)

## all .o based on all .cpp
OBJS        := $(SRCS:.cpp=.o)


## need libs, add at here
LIBS := pthread

## used headers  file path
INCLUDE_PATH := .

## used include librarys file path
LIBRARY_PATH := /lib

## debug for debug info, when use gdb to debug
ifeq (1, ${DBG_ENABLE}) 
	CFLAGS += -D_DEBUG -O0 -g -DDEBUG=1
endif

## get all include path
CFLAGS  += $(foreach dir, $(INCLUDE_PATH), -I$(dir))

## get all library path
LDFLAGS += $(foreach lib, $(LIBRARY_PATH), -L$(lib))

## get all librarys
LDFLAGS += $(foreach lib, $(LIBS), -l$(lib))


all: clean build $(TARGET)

build:
	g++ client.cpp -o client -lpthread
	g++ service.cpp -o service -lpthread

clean:
	$(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 网络抓包_Stream抓包软件[通俗易懂]分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/69807.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注