From 93ec33f5b601dcf0be29ca738317c8f08aac799a Mon Sep 17 00:00:00 2001 From: flykhan Date: Fri, 22 Sep 2023 23:25:11 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BD=91=E7=BB=9C=E9=83=A8=E5=88=86=E9=98=B6?= =?UTF-8?q?=E6=AE=B5=E6=B5=8B=E8=AF=95=E7=BC=96=E7=A8=8B=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- exam/t1_client | Bin 0 -> 9136 bytes exam/t1_client.c | 62 ++++++++++++++++++++++ exam/t1_server | Bin 0 -> 9192 bytes exam/t1_server.c | 50 ++++++++++++++++++ exam/t2.c | 89 ++++++++++++++++++++++++++++++++ exam/t3.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 333 insertions(+) create mode 100755 exam/t1_client create mode 100644 exam/t1_client.c create mode 100755 exam/t1_server create mode 100644 exam/t1_server.c create mode 100644 exam/t2.c create mode 100644 exam/t3.c diff --git a/exam/t1_client b/exam/t1_client new file mode 100755 index 0000000000000000000000000000000000000000..04c8c1fe8bd33e3b004856b1f746e0574af0e6bf GIT binary patch literal 9136 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 MTrgg?7`N8{A7C@vVE_OC literal 0 HcmV?d00001 diff --git a/exam/t1_client.c b/exam/t1_client.c new file mode 100644 index 0000000..86c3163 --- /dev/null +++ b/exam/t1_client.c @@ -0,0 +1,62 @@ +// 利用 setsocketopt() 使用嵌套字支持广播,并编写两个程序,其中一个发送广播数据,另一个接收广播数据 +// 客户端 +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/exam/t1_server b/exam/t1_server new file mode 100755 index 0000000000000000000000000000000000000000..7d0534cb57c404477903063ae71cb02517c19cdd GIT binary patch literal 9192 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 +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/exam/t2.c b/exam/t2.c new file mode 100644 index 0000000..598e4f1 --- /dev/null +++ b/exam/t2.c @@ -0,0 +1,89 @@ +// 写一个 TCP 并发的服务器,实现 echo 功能 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/exam/t3.c b/exam/t3.c new file mode 100644 index 0000000..d758a1a --- /dev/null +++ b/exam/t3.c @@ -0,0 +1,132 @@ +/* +* 写一个网络数据分析器 +* 要求: +* 1、对 arp/ip/tcp/udp 数据进行区分。 +* 2、把数据包中的源信息,目的信息等重要的信息打印出来。 +*/ +#include +#include +#include +#include +#include // memset +#include // ether_header +#include // ip +#include // ether_arp +#include // 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; +}