(9)下:学习与验证 linux 里的 epoll 对象里的 EPOLLIN、 EPOLLHUP 与 EPOLLRDHUP 的不同。小例子的实验

(4)本实验代码的蓝本,是伊圣雨老师里的课本里的代码,略加改动而来的。
++以下是 服务器端的代码:

在这里插入图片描述

++ 每当收到客户端的报文时,就测试一下对应的 epoll 事件里的事件标志,不读取报文内容,所以设置为 ET 边缘触发模式。
++ 对应的代码版本 :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <fcntl.h> //增加这俩头文件
#include <errno.h>

#define EPOLL_SIZE  50

int main(int argc,char * argv[])
{   //验证 EPOLLHUP 等标志的服务器端, argc = 2
    int serv_sock, clnt_sock, str_len, i, epfd, event_cnt;
    struct sockaddr_in serv_adr, clnt_adr;
    socklen_t adr_sz;  
    struct epoll_event event, * ep_events;

    if(argc != 2) { printf("参数不是2个\n");exit(1); }

    serv_sock = socket(PF_INET,SOCK_STREAM,0);
    printf("创建了监听套接字,描述符为: %d\n",serv_sock);

    memset(&serv_adr,0,sizeof(serv_adr));
    serv_adr.sin_family = AF_INET; // 协议
    serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址
    serv_adr.sin_port = htons(atoi(argv[1])); //端口号

    bind( serv_sock,
        (struct sockaddr *)&serv_adr, sizeof(serv_adr) ) ;
    listen(serv_sock,5);

    epfd = epoll_create(EPOLL_SIZE); // EPOLL_SIZE = 50
    event.events  = EPOLLIN; // 监听套接字仍为水平触发模式
    event.data.fd = serv_sock;
    epoll_ctl(epfd, EPOLL_CTL_ADD, serv_sock, &event);

    ep_events = malloc(sizeof(struct epoll_event) * EPOLL_SIZE);
    while (1) // 此循环在正常情况下是不会退出的。
    {   event_cnt = epoll_wait(epfd, ep_events, EPOLL_SIZE, -1);       
        if(-1 == event_cnt) {  break; } // 出错则结束循环,进程退出   

        puts("从 epoll_wait() 返回了");//统计epoll_wait()的返回次数
        for(i = 0 ; i < event_cnt ; i++) //依次处理所有发生了事件的套接字
        {   if(ep_events[i].data.fd == serv_sock)//监听套接字
            {   adr_sz = sizeof(clnt_adr);
                clnt_sock = accept( serv_sock,
                                (struct sockaddr *)&clnt_adr,&adr_sz );
                event.events = EPOLLIN | EPOLLHUP |EPOLLRDHUP | EPOLLET ;
                    // 通信套接字用边缘触发是因为不准备读取报文
                event.data.fd = clnt_sock; 
                epoll_ctl(epfd, EPOLL_CTL_ADD, clnt_sock, &event); 
                printf("创建了通信套接字 id: %d\n", clnt_sock);
            } else { // 依次测试通讯套接字上有事件时具有的 epoll标志。
                uint32_t revents = ep_events[i].events; 
                int fd = ep_events[i].data.fd;

                if( revents & EPOLLIN    ) 
                    printf("通信套接字 %d 上有 EPOLLIN    事件\n", fd);
                if( revents & EPOLLHUP   ) 
                    printf("通信套接字 %d 上有 EPOLLHUP   事件\n", fd);
                if( revents & EPOLLRDHUP ) 
                    printf("通信套接字 %d 上有 EPOLLRDHUP 事件\n", fd);
            }
        } // for(...)  
    } // while(...)
    
    return 0;  
}

(5) 接着给出客户端的版本,这是一个 linux 版本的客户端,很简单的小程序

在这里插入图片描述

++ 记录其源代码版本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

int main(int argc,char * argv[])
{   // 回声客户端,三个参数,argc = 3
    int  sock, str_len;  
    struct sockaddr_in  serv_adr;
    if(argc != 3) { printf("参数不是3个\n");exit(1); }

    sock = socket(PF_INET,SOCK_STREAM,0);

    memset(&serv_adr,0,sizeof(serv_adr));
    serv_adr.sin_family = AF_INET;
    // serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
    // inet_addr() 的语义不明,不好
    // 处理文本地址,只需使用 inet_pton() 与 inet_ntop() 即可。
    // int inet_pton(int af, const char *src, void *dst);
    inet_pton(AF_INET, argv[1], &serv_adr.sin_addr.s_addr);
    serv_adr.sin_port = htons(atoi(argv[2]));

    if(connect(sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) != -1)
        puts("客户端套接字连接至服务器成功\n");

    sleep(60); // 延迟 60s 以观察实验结果

    close(sock); // 此行可注释,以验证 四次握手与 RST 报文的出现时机
    exit(0);
}

(6)后来实验中发现,客户端采用 linux 版本,会导致 wireshark 无法抓包,只好再编写 windows 版本的客户端,源代码如下:

在这里插入图片描述

++ 代码版:

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

#pragma warning(disable : 4996) // 禁用关于 inet_addr 的过时警告

int main() 
{
	WSADATA m_wsadata; // 在 windows平台使用 socket前,须做一下初始化,
	WSAStartup(0x0202, &m_wsadata); // 最后用 WSACleanup() 释放库。

	SOCKET sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	SOCKADDR_IN       server_in;
	memset(&server_in, 0, sizeof(SOCKADDR_IN));  //连接服务器
	server_in.sin_family = AF_INET;
	server_in.sin_port = htons(9000); // 连接至 80 端口
	server_in.sin_addr.s_addr = inet_addr("192.168.1.126");

	connect(sClient, (struct sockaddr*)&server_in, sizeof(SOCKADDR_IN));

	for (int i = 0; i < 1000000000; i++); // 延时一下

	closesocket(sClient); // 关闭套接字的函数
	WSACleanup();         // 用这个函数关闭库
	return 0; 
}

++ 使用 windows 的套接字,还要设置一下 vs2019 ,要不然上面的代码会找不到外部函数

在这里插入图片描述

++ 以及:

在这里插入图片描述

(7) 以下给出实验结果,配合 wireshark 抓包

在这里插入图片描述

(8)

谢谢

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962984.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Python】第七弹---Python基础进阶:深入字典操作与文件处理技巧

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】【Python】 目录 1、字典 1.1、字典是什么 1.2、创建字典 1.3、查找 key 1.4、新增/修改元素 1.5、删除元素 1.6、遍历…

[Linux]从零开始的STM32MP157 U-Boot移植

一、前言 在上一次教程中&#xff0c;我们了解了STM32MP157的启动流程与安全启动机制。我们还将FSBL的相关代码移植成功了。大家还记得FSBL的下一个步骤是什么吗&#xff1f;没错&#xff0c;就是SSBL&#xff0c;而且常见的我们将SSBL作为存放U-Boot的地方。所以本次教程&…

消息队列篇--原理篇--常见消息队列总结(RabbitMQ,Kafka,ActiveMQ,RocketMQ,Pulsar)

1、RabbitMQ 特点&#xff1a; AMQP协议&#xff1a;RabbitMQ是基于AMQP&#xff08;高级消息队列协议&#xff09;构建的&#xff0c;支持多种消息传递模式&#xff0c;如发布/订阅、路由、RPC等。多语言支持&#xff1a;支持多种编程语言的客户端库&#xff0c;包括Java、P…

家居EDI:Hom Furniture EDI需求分析

HOM Furniture 是一家成立于1977年的美国家具零售商&#xff0c;总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品&#xff0c;满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…

【go语言】数组和切片

一、数组 1.1 什么是数组 数组是一组数&#xff1a;数组需要是相同类型的数据的集合&#xff1b;数组是需要定义大小的&#xff1b;数组一旦定义了大小是不可以改变的。 1.2 数组的声明 数组和其他变量定义没有什么区别&#xff0c;唯一的就是这个是一组数&#xff0c;需要给…

51单片机 01 LED

一、点亮一个LED 在STC-ISP中单片机型号选择 STC89C52RC/LE52RC&#xff1b;如果没有找到hex文件&#xff08;在objects文件夹下&#xff09;&#xff0c;在keil中options for target-output- 勾选 create hex file。 如果要修改编程 &#xff1a;重新编译-下载/编程-单片机重…

HTML一般标签和自闭合标签介绍

在HTML中&#xff0c;标签用于定义网页内容的结构和样式。标签通常分为两类&#xff1a;一般标签&#xff08;也称为成对标签或开放闭合标签&#xff09;和自闭合标签&#xff08;也称为空标签或自结束标签&#xff09;。 以下是这两类标签的详细说明&#xff1a; 一、一般标…

【EasyX 图形化编程保姆级喂嘴里教程】(C/C++) graphics.h 头文件库安装

文章目录 EasyXEasyX 是什么&#xff1f;超低的学习成本超多的应用场景超轻的发布过程 EasyX安装下载好后打开安装文件, 点击下一步。它自动检测已有的IDE&#xff0c;自行选择安装点击安装会提示安装成功接下来就可以在代码中使用 graphics.h 头文件库 EasyX EasyX 是什么&am…

吊打同类软件免费又可批量使用

聊一聊 对于经常用到席卡的人来说&#xff0c;每次打印都觉得麻烦&#xff0c;要是有个软件&#xff0c;直接输入名称就能打印就好了。 这不&#xff0c;只要你想&#xff0c;就肯定能实现&#xff1b;如果没实现&#xff0c;就说明你不够想。 这个软件我测试了下&#xff0…

2.攻防世界PHP2及知识点

进入题目页面如下 意思是你能访问这个网站吗&#xff1f; ctrlu、F12查看源码&#xff0c;什么都没有发现 用kali中的dirsearch扫描根目录 命令如下&#xff0c;根据题目提示以及需要查看源码&#xff0c;扫描以php、phps、html为后缀的文件 dirsearch -u http://61.147.17…

网络工程师 (11)软件生命周期与开发模型

一、软件生命周期 前言 软件生命周期&#xff0c;也称为软件开发周期或软件开发生命周期&#xff0c;是指从软件项目的启动到软件不再被使用为止的整个期间。这个过程可以细分为多个阶段&#xff0c;每个阶段都有其特定的目标、任务和产出物。 1. 问题定义与需求分析 问题定义…

深度学习练手小例子——cifar10数据集分类问题

CIFAR-10 是一个经典的计算机视觉数据集&#xff0c;广泛用于图像分类任务。它包含 10 个类别的 60,000 张彩色图像&#xff0c;每张图像的大小是 32x32 像素。数据集被分为 50,000 张训练图像和 10,000 张测试图像。每个类别包含 6,000 张图像&#xff0c;具体类别包括&#x…

力扣257. 二叉树的所有路径(遍历思想解决)

Problem: 257. 二叉树的所有路径 文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(利用二叉树的先序遍历) 利用先序遍历的思想&#xff0c;我门用一个List变量path记录当前先序遍历的节点&#xff0c;当遍历到根节点时&#xff0c;将其添加到另一个List变量res中&…

力扣第149场双周赛

文章目录 题目总览题目详解找到字符串中合法的相邻数字重新安排会议得到最多空余时间I 第149场双周赛 题目总览 找到字符串中合法的相邻数字 重新安排会议得到最多空余时间I 重新安排会议得到最多空余时间II 变成好标题的最少代价 题目详解 找到字符串中合法的相邻数字 思…

算法题(54):插入区间

审题&#xff1a; 需要我们把newinterval的区间与interval的区间合并起来&#xff0c;并返回合并后的二维数组地址 思路&#xff1a; 方法一&#xff1a;排序合并区间 我们可以先把newinterval插入到interval中&#xff0c;进行排序然后复用合并区间的代码 方法二&#xff1a;模…

网工_HDLC协议

2025.01.25&#xff1a;网工老姜学习笔记 第9节 HDLC协议 9.1 HDLC高级数据链路控制9.2 HDLC帧格式&#xff08;*控制字段&#xff09;9.2.1 信息帧&#xff08;承载用户数据&#xff0c;0开头&#xff09;9.2.2 监督帧&#xff08;帮助信息可靠传输&#xff0c;10开头&#xf…

[免费]微信小程序智能商城系统(uniapp+Springboot后端+vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序智能商城系统(uniappSpringboot后端vue管理端)&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序智能商城系统(uniappSpringboot后端vue管理端) Java毕业设计_哔哩哔哩_bilibili 项目介绍…

nth_element函数——C++快速选择函数

目录 1. 函数原型 2. 功能描述 3. 算法原理 4. 时间复杂度 5. 空间复杂度 6. 使用示例 8. 注意事项 9. 自定义比较函数 11. 总结 nth_element 是 C 标准库中提供的一个算法&#xff0c;位于 <algorithm> 头文件中&#xff0c;用于部分排序序列。它的主要功能是将…

CF 581A.Vasya the Hipster(Java实现)

题目分析 红色袜子数量a&#xff0c;蓝色袜子数量b&#xff0c;题目是个潮哥儿&#xff0c;首先选择两种袜子混搭&#xff0c;搭不出来就纯色 思路分析 混搭数量取决于最小数量&#xff0c;剩余的纯色数量取决于哪个还有剩余且数量要/2 代码 import java.util.*;public class…