Java中的生产者/消费者问题是一种典型的多线程同步问题,涉及到资源的共享和协作。在该问题中,生产者线程负责生成数据并放入共享存储区(如缓冲区),而消费者线程则负责从存储区取出数据进行处理。如果不进行有效的同步控制,可能会导致两种不期望的情况:一是缓冲区满,生产者继续生产导致数据溢出;二是缓冲区空,消费者持续等待,造成资源浪费。 为了解决这个问题,Java提供了线程同步机制,包括`synchronized`关键字、`wait()`、`notify()`和`notifyAll()`方法。在上述示例中,这些机制被巧妙地运用到`CubbyHole`类中。 `CubbyHole`类代表了共享的存储空间,包含一个`contents`变量表示当前存储的数据,以及一个`available`布尔变量表示存储空间是否可用。`get()`方法是消费者获取数据的操作,`put()`方法是生产者放入数据的操作,这两个方法都被声明为`synchronized`,这意味着同一时间只能有一个线程执行它们。 在`get()`方法中,当`available`为`false`时,表示缓冲区无数据,消费者需要等待,调用`wait()`进入等待状态。同样,在`put()`方法中,当`available`为`true`时,表示缓冲区已满,生产者也需要等待。调用`wait()`会让线程释放锁并进入等待队列。当条件满足后,`notifyAll()`方法会唤醒所有等待的线程,但只有一个线程能获得锁并继续执行,其余线程重新进入等待状态。 `Producer`和`Consumer`类分别代表生产者和消费者线程。它们都继承自`Thread`类,并重写`run()`方法来执行特定的任务。生产者在`run()`方法中调用`put()`方法放入数据,并使用`sleep()`模拟生产数据的时间延迟。消费者在`run()`方法中调用`get()`方法获取数据,循环10次。 上述代码的运行结果展示了生产者和消费者交替进行操作的过程,确保了生产者不会在缓冲区满时继续生产,消费者也不会在缓冲区为空时盲目等待。这种解决方案有效地避免了死锁问题,实现了生产者和消费者之间的协调工作。 总结来说,Java中的生产者/消费者问题的解决策略主要包括: 1. 使用`synchronized`关键字确保对共享资源的互斥访问。 2. 通过`wait()`、`notify()`和`notifyAll()`方法实现线程间的通信与协作,控制生产者和消费者的执行顺序。 3. 设计合适的数据结构(如`CubbyHole`)来表示共享资源,以及相关的状态标志(如`available`)来判断资源是否可用。 通过这种方式,我们可以在多线程环境中有效地管理和共享资源,提高程序的并发性和效率。
1
易语言是一种专为中国人设计的编程语言,它以简体中文作为编程符号,降低了编程的门槛,使得更多的人能够理解并参与到程序开发中。在易语言中,CopyFileEx是一个非常重要的函数,用于实现文件的复制操作,具有丰富的功能和灵活的选项。本使用例程将详细介绍如何在易语言中应用CopyFileEx函数。 CopyFileEx函数通常在处理文件复制时提供更高级别的控制,比如可以设置进度条、复制完成后执行操作等。在易语言中,这个函数的使用方法可能与其他编程语言略有不同,因为易语言的设计理念是让代码更接近自然语言。下面我们将深入探讨CopyFileEx的使用方法和相关知识点。 CopyFileEx函数的主要参数包括源文件路径、目标文件路径以及一个回调函数指针,用于处理复制过程中的事件。在易语言中,你需要定义这些参数,并根据需要设置其他可选参数,如是否覆盖已存在的目标文件、是否复制文件属性等。 1. **源文件路径**:这是要复制的原始文件的完整路径。在易语言中,你可以使用字符串类型来表示,确保路径正确无误,包括盘符、目录和文件名。 2. **目标文件路径**:这是复制后文件的新位置。同样,使用字符串类型表示,确保路径有效且目标目录存在。 3. **回调函数**:这是一个特殊的函数,用于在复制过程中接收进度更新或执行自定义操作。在易语言中,你需要定义一个符合特定接口的函数,并将其地址作为参数传递给CopyFileEx。 4. **其他参数**:易语言的CopyFileEx可能还包括一些布尔类型的参数,如`bFailIfExists`(如果目标文件已存在是否失败)、`bReplaceExisting`(是否替换已存在的目标文件)等。根据需求设置这些参数,可以控制复制行为。 在使用CopyFileEx例程前,你需要了解如何在易语言中定义函数、处理字符串、检查路径有效性等基本操作。在源码中,你可能会看到类似这样的调用: ```易语言 .易语言CopyFileEx("源文件路径", "目标文件路径", .回调函数, .用户数据, .bFailIfExists, .bReplaceExisting) ``` 这里的`.回调函数`和`.用户数据`是自定义的,可以根据需要进行设置。`.用户数据`可以是你想要传递到回调函数的任何数据,而`.回调函数`则需要定义一个处理CopyFileEx进度的函数。 在编写回调函数时,你可能需要处理以下事件: - 文件复制开始 - 文件复制进度更新 - 文件复制完成 - 文件复制出错 回调函数的参数通常包括当前复制的字节数、总字节数、用户数据等,你可以根据这些信息更新进度条或者显示复制状态。 通过以上讲解,你应该对易语言中的CopyFileEx使用有了基本的理解。实际操作中,你可以参考提供的"CopyFileEx使用例程"源码,逐步学习和调试,以加深对这一功能的理解。记得在实践中不断尝试和优化,这样你的编程技能将得到显著提升。
2025-08-23 23:30:37 3KB CopyFileEx
1
《Qt 5开发及实例(第4版)》是由陆文周编著的一本深入浅出的Qt编程书籍,该书结合丰富的实例,详细讲解了Qt 5框架的使用和开发技巧。Qt是一个跨平台的应用程序开发框架,广泛应用于桌面、移动以及嵌入式设备上。这本书的第4版不仅涵盖了基本的Qt组件和API,还加入了最新的Qt 5特性和最佳实践。 在源代码部分,我们可以看到一系列以“CH”命名的文件夹,这些代表了书中的各个章节。每个章节可能包含多个实例代码,帮助读者理解和实践Qt编程。让我们逐一探讨这些章节可能涉及的知识点: 1. **CH1:基础篇** - 这部分通常会介绍Qt开发环境的搭建,包括安装Qt Creator和编译器,以及如何创建和运行第一个Qt项目。还会讲解Qt的基本概念,如信号与槽机制、对象模型和事件处理。 2. **CH5:图形视图框架** - Qt 5的图形视图框架提供了强大的图形渲染和交互能力。这里可能会讨论QGraphicsView和QGraphicsItem的使用,以及如何实现自定义图形元素和动画效果。 3. **CH9、CH10、CH12、CH14** - 这些章节可能涉及用户界面设计,如窗口和对话框的创建,常用控件(按钮、文本框、列表视图等)的使用,以及布局管理,确保界面在不同屏幕尺寸下都能良好显示。 4. **CH11** - 可能会讲解多线程编程,如何利用QThread进行并发处理,避免阻塞UI,提高应用性能。 5. **CH19、CH21、CH22** - 高级主题,如网络编程(使用QTcpSocket和QUdpSocket),数据库访问(QSqlModel和QSqlDatabase),以及XML和JSON数据的读写。 6. **CH23、CH24** - 可能涉及Qt的多媒体支持,如音频和视频播放,以及移动设备和嵌入式系统的开发,例如触摸事件处理和屏幕旋转支持。 通过这本书的学习,开发者不仅可以掌握Qt 5的基本用法,还能了解如何编写高效、可维护的Qt应用程序。书中每个章节的源代码实例都是精心设计的,旨在帮助读者加深理解,提升实际编程技能。特别地,书中的“典型案例视频分析”将理论与实践紧密结合,为学习过程提供更直观的辅助。 在实际操作中,精简源代码的步骤是必要的,以减少编译后的过程文件,优化存储空间,同时也有助于代码的整洁和维护。对于初学者,这是一次了解软件工程实践的好机会,学习如何组织和管理项目文件。《Qt 5开发及实例(第4版)》是深入学习Qt编程的宝贵资源,无论是对个人还是团队,都将带来显著的提升。
2025-08-23 17:10:26 45.58MB
1
【Python编程基础与实例】 在Python编程中,实践是学习的关键。通过编写各种实例,可以更好地理解和掌握语言的特性和语法。以下四个Python实例代码分别涉及数组操作、数学计算、逻辑判断以及日期处理,这些都是Python编程的基础知识。 1. **数组操作与条件判断** 题目要求组合不同的数字形成三位数,并排除重复。在这个问题中,我们使用嵌套循环遍历数字1到4,通过条件判断避免重复组合。Python的for循环和if语句在这里起到了核心作用。例如: ```python for i in range(1, 5): for j in range(1, 5): for k in range(1, 5): if i != j and i != k and j != k: print(i, j, k) ``` 这段代码展示了如何通过循环结构生成所有可能的无重复数字的三位数组合。 2. **百分比提成计算** 本题涉及到根据利润范围计算奖金,需要用到条件分支(if-elif-else)来处理不同利润区间的提成率。两种解法,一种是逐一判断利润区间并计算奖金,另一种是利用列表和索引进行计算。例如: ```python while True: I = float(input("请输入利润:")) if I <= 10: a = I * 0.01 print(a) # ... 其他区间计算 ... ``` 或者: ```python arr = [1000000, 600000, 400000, 200000, 100000, 0] rat = [0.01, 0.015, 0.03, 0.05, 0.075, 0.1] I = int(input('净利润:')) r = 0 for idx in range(0, 6): if I > arr[idx]: r = r + (I - arr[idx]) * rat[idx] I = arr[idx] print(r) ``` 这段代码展示了如何根据用户输入计算不同利润区间的奖金总额。 3. **完全平方数检测** 问题是寻找一个整数,使得其加100和加268后都是完全平方数。这个问题可以通过遍历整数并计算平方根来解决,结合Python的math模块,如: ```python import math for i in range(10000): x = int(math.sqrt(i + 100)) y = int(math.sqrt(i + 268)) if x * x == i + 100 and y * y == i + 268: print(i) ``` 这段代码展示了如何利用数学函数来解决数学问题,并找到了符合条件的整数。 4. **日期计算** 要求根据输入的年月日计算出是当年的第几天。Python的日期和时间处理可以使用内置的datetime模块,但这里假设我们手动计算。例如: ```python def day_of_year(year, month, day): days_in_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] total_days = sum(days_in_month[:month]) if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0): days_in_month[2] += 1 # 闰年2月多一天 return total_days + day year = int(input("输入年份:")) month = int(input("输入月份:")) day = int(input("输入日期:")) print("这是当年的第", day_of_year(year, month, day), "天") ``` 这段代码演示了如何计算给定日期是一年中的第几天,考虑了闰年的情况。 通过这些实例,我们可以看到Python在处理数值计算、逻辑判断、数据结构和日期操作时的灵活性。在学习Python的过程中,不断练习这样的小例子有助于加深对语言特性的理解,并提高编程能力。
2025-08-23 16:14:26 346KB python
1
在C#编程语言中,委托和事件是两个关键特性,它们是实现事件驱动编程的核心工具。委托可以看作是类型安全的函数指针,允许我们传递方法作为参数,而事件则是一种特殊的委托,用于实现发布-订阅模式,使得对象可以在需要时通知其他对象。 我们来理解“委托”这个概念。在C#中,委托类型定义了一种方法签名,它允许存储和调用一个或多个具有相同签名的方法。委托实例可以指向一个方法,或者通过`+`和`-`运算符链式指向多个方法。这样,我们就可以在程序的不同部分之间传递方法调用,提高代码的灵活性和可复用性。例如: ```csharp public delegate void MyDelegate(string message); public class MyClass { public event MyDelegate MyEvent; public void RaiseEvent(string message) { if (MyEvent != null) MyEvent(message); } } ``` 在这个例子中,`MyDelegate`是一个定义了接受一个字符串参数并返回无值类型的委托。`MyClass`有一个名为`MyEvent`的事件,它是`MyDelegate`类型的。`RaiseEvent`方法会触发这个事件,如果有任何订阅者的话。 接下来,我们讨论“事件”。事件是委托的特殊使用,它定义了一个从发布者到订阅者的通信渠道,确保发布者不会直接调用订阅者的代码。这种设计模式遵循了观察者模式的原则,使得对象可以在不直接了解彼此的情况下进行交互。事件通常与控件和UI组件相关,比如按钮点击事件、文本框更改事件等。 ```csharp public class Subscriber { public void OnMessageReceived(string message) { Console.WriteLine("Received message: " + message); } } public class Program { static void Main() { MyClass myClass = new MyClass(); Subscriber mySubscriber = new Subscriber(); myClass.MyEvent += mySubscriber.OnMessageReceived; myClass.RaiseEvent("Hello, World!"); // Unsubscribe myClass.MyEvent -= mySubscriber.OnMessageReceived; } } ``` 在上面的例子中,`Subscriber`类的`OnMessageReceived`方法订阅了`MyClass`的`MyEvent`。当`RaiseEvent`被调用时,`OnMessageReceived`会被执行。通过`+=`操作符订阅事件,`-=`操作符取消订阅,控制了事件处理的生命周期。 委托和事件的组合使得C#代码更加模块化和可维护,尤其是在UI编程中,它们允许我们将界面逻辑和业务逻辑分离。同时,委托也可以用于实现回调机制,使得异步编程变得更加简单。理解和掌握C#的委托事件对于任何想要深入学习.NET框架的开发者来说都是至关重要的。通过实例学习,初学者和进阶者都能从中受益匪浅,提升自己的编程技能。
2025-08-23 10:33:59 200KB 委托事件实例
1
Python是一种功能强大的高级编程语言,广泛应用于Web开发、数据分析和人工智能等多个领域。它以简洁的语法和丰富的库而闻名,尤其在自动化脚本编写方面表现出色。在网络安全和验证码破解领域,Python常被用来开发代码以绕过各种验证机制。近期,一个压缩包引起了关注,其中似乎包含了针对阿里巴巴(阿里)特定滑块验证码X82YX5SEC的Python代码。滑块验证码是一种常见的安全措施,用于防止机器人和自动化程序滥用服务,通常要求用户手动拖动滑块完成拼图,以验证用户是否为真实人类。 压缩包中的“x5sec-X82Y.py”文件可能包含了破解该滑块验证码的Python代码。X5Sec可能是阿里安全组件的一部分,而X82Y可能是该组件的特定版本或某种滑块类型。该脚本可能涉及分析滑块验证码图片、识别滑块位置以及模拟用户拖动滑块等关键步骤。另一个文件“通用滑块.py”则暗示其可能是一个适用于多种滑块验证码的通用解决方案,包含通用算法,能够适应不同滑块验证的实现方式。 此外,压缩包中还包含一个名为“客户端-1.6.exe”的Windows可执行文件,这可能是阿里提供的一个测试环境,用于模拟滑块验证码的显示和交互。还有一个名为“易语言编写,可能会报毒.txt”的文件,其内容可能与易语言(一种中国本土编程语言)编写的代码有关。由于易语言的某些特性,编译后的程序可能会被杀毒软件误报为病毒。 这些资源可能是为了教学或研究目的,展示了如何使用Python结合图像处理、模式识别和网络请求技术来自动化处理验证码。然而,这种行为可能违反了服务提供商的使用条款,甚至可能涉及法律问题。因此,在实际操作时,必须确保遵循合法合规的原则,谨慎行事。
2025-08-23 05:09:59 56KB Python 滑块验证码
1
ESP32是一款强大的、集成Wi-Fi和蓝牙(包括BLE)功能的32位微控制器,由Espressif Systems公司开发。在物联网(IoT)应用中,它被广泛用于无线通信和远程控制。"OTA.zip"是博主李法师提供的一个关于ESP32设备的Over-the-Air(OTA)更新样例资源文件,它可以帮助开发者了解和实践如何通过网络对ESP32固件进行远程升级。 OTA(Over-the-Air)技术允许设备通过无线网络接收新的固件更新,而无需物理连接到电脑或其他设备。这对于分布广泛且难以手动更新的物联网设备来说尤其重要。ESP32的OTA功能使得设备能够安全地在线升级,减少了维护成本并提高了效率。 在ESP32中实现OTA更新,主要涉及以下几个关键步骤: 1. **环境配置**:你需要在ESP32开发环境中集成OTA相关的库,如Arduino ESP32库中的`WiFi`和`Update`库。确保开发环境(如Arduino IDE或PlatformIO)已经安装了最新版本,并且配置了正确的硬件平台。 2. **服务器设置**:创建一个HTTP或HTTPS服务器来托管新的固件映像。这个服务器可以是云服务,也可以是你自己的本地服务器。固件文件通常以.bin格式提供,以便ESP32能识别并加载。 3. **固件构建**:使用开发工具将更新后的代码编译成.bin文件。每个ESP32项目都会有一个唯一的固件映像,包含了所有需要运行的程序和库。 4. **OTA API实现**:在ESP32的应用代码中,你需要编写API接口来处理OTA请求。这包括连接到服务器,检查是否有可用更新,下载新固件,以及安全地重启设备以应用更新。 5. **客户端设备更新**:在客户端设备端,用户或系统会触发OTA更新流程。这可能通过用户界面操作,或者根据预设的条件自动执行,比如检测到新版本时。设备连接到服务器,验证更新,然后下载固件文件。 6. **安全考虑**:在进行OTA更新时,确保固件签名和验证过程是安全的至关重要。ESP32支持安全启动和固件签名,以防止恶意软件注入。在下载和应用更新前,设备应验证固件的完整性和来源。 7. **错误处理与恢复**:在更新过程中可能出现各种问题,比如网络中断、下载失败等。因此,良好的错误处理机制是必要的,包括重试机制和在更新失败时回滚到旧固件的能力。 通过李法师的这个"OTA.zip"样例,开发者可以学习到具体的代码实现,理解如何将上述步骤整合进实际项目中。这个资源文件可能包含了示例代码、配置文件、服务器部署指南等内容,帮助开发者快速上手ESP32的OTA更新功能。 ESP32的OTA功能是其在物联网应用中的强大特性之一,通过有效的OTA更新策略,可以确保设备保持最新,优化性能,修复潜在问题,并引入新的功能。学习和掌握这一技术,对于任何从事ESP32开发的人员都极其有价值。
2025-08-22 18:24:53 42.85MB ESP32
1
在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC) 库结合FFmpeg库实现DXVA2(DirectX Video Acceleration 2)硬件解码技术。DXVA2是微软提供的一个API,它允许视频播放应用程序利用现代显卡的硬件加速能力来解码高清视频,从而减轻CPU负担并提高性能。 我们需要理解MFC。MFC是一个由微软开发的C++类库,用于简化Windows应用程序的开发。它封装了Windows API,提供了面向对象的接口,使得开发者可以更方便地构建用户界面、数据库连接等。 FFmpeg则是一个开源的多媒体处理框架,包含了解码、编码、转换、流媒体等多种功能。FFmpeg支持多种视频编解码器,包括硬件加速的解码器,如DXVA2。 实现MFC与FFmpeg的结合,首先你需要在项目中集成FFmpeg库。这通常涉及到下载源代码,配置编译环境,然后将编译好的静态库或动态库链接到你的MFC项目中。确保在链接FFmpeg时包含了必要的硬件加速模块,例如对于DXVA2,需要包含`libavcodec`和`libavutil`等组件。 接下来,你需要创建一个MFC应用,设置合适的窗口类和消息处理机制。在主窗口中,你可能需要创建一个用于显示视频的控件,如CDC(设备上下文)或者CStatic,这样可以接收和渲染解码后的帧。 在MFC应用中使用DXVA2硬件解码,你需要: 1. 初始化FFmpeg上下文:创建`AVFormatContext`,打开视频文件,并解析流信息。 2. 找到支持DXVA2的解码器:通过`avcodec_find_decoder()`找到合适的解码器,检查其是否支持DXVA2硬件加速。 3. 创建解码上下文:调用`avcodec_open2()`打开解码器,并在选项中设置硬件加速参数。 4. 分配DXVA2解码表面:使用DirectX API创建Direct3D设备和交换链,然后创建DXVA2配置和解码表面。 5. 解码视频帧:通过`avcodec_decode_video2()`函数提交编码数据到解码器,该函数会利用硬件加速进行解码。解码后的帧存储在DXVA2表面中。 6. 渲染解码后的帧:使用Direct3D API,从DXVA2表面提取并绘制到MFC的显示控件上。 7. 关闭并释放资源:当不再需要解码时,释放所有分配的资源,包括解码上下文、解码表面和Direct3D设备。 在实践中,你还需要处理各种错误情况,例如硬件加速不支持、文件格式错误等。同时,为了保证流畅播放,你需要考虑缓冲管理和多线程同步,以及如何在视频播放过程中处理关键帧和非关键帧。 这个名为"Dxva2Test"的实例应该包含一个完整的MFC应用程序,演示了上述步骤。通过学习和分析这个例子,你可以了解到如何在实际项目中结合MFC和FFmpeg实现高效的硬件解码。请注意,具体实现细节可能因不同的FFmpeg版本和系统环境而有所不同,因此在实际操作时,可能需要根据实际情况进行调整。
2025-08-22 15:10:18 54.77MB DXVA2
1
在微控制器(MCU)中,Bootloader(引导加载程序)是一个非常重要的组成部分,它负责在系统启动时执行一系列初始化操作,并为后续的应用程序提供一个合适的运行环境。 硬件环境:STM32F103C8T6 (Flash 64K RAM 20K) 教程参考:韦东山老师“基于单片机从零写BootLoader” 参考对应配套文章:https://blog.csdn.net/studyingdda/article/details/143265494?spm=1001.2014.3001.5501 在微控制器编程领域,Bootloader是一个基础但至关重要的组件,它在系统上电或复位后首先被执行,主要职责是初始化硬件设备、建立运行环境,以及最终加载主应用程序。在本文中,我们将深入探讨一个基于STM32F103C8T6微控制器的双区Bootloader代码示例,这是一种常见的32位ARM Cortex-M3微控制器,拥有64KB的闪存和20KB的RAM。 Bootloader的具体实现方式多种多样,可以根据应用需求以及硬件特性的不同而改变。在本示例中,Bootloader被设计为具备双区功能,这意味着它能够管理两块应用程序存储区域,一块用于存放当前运行的应用程序,另一块用于存放待更新或备选的应用程序。当主应用程序出现故障或需要更新时,Bootloader可以从备份区域安全地将新的应用程序代码复制到主应用程序区域,并重新启动系统,从而保证了系统的可靠性和更新的灵活性。 在本示例中,我们将会看到Bootloader如何实现以下几个关键步骤: 1. 重定位vector表。vector表存放中断向量,引导加载程序可能需要将其移动到RAM或其他位置,以确保应用程序启动时可以正确响应中断。 2. APP自我复制。这是指Bootloader能够实现将备份区的代码复制到主应用区的功能,确保更新过程的顺利进行。 3. 使用汇编跳转。汇编语言提供了直接的硬件操作能力,在Bootloader跳转到应用程序执行的过程中,汇编语言的使用是不可或缺的。 4. APP有无异常向量。这里的异常向量指的是应用程序中可能用到的特殊中断处理程序,Bootloader需要识别并妥善处理这些异常向量。 5. BootLoader根据头部信息复制APP。Bootloader通过分析存储在APP头部的信息,如版本号、校验和等,来决定是否需要执行复制操作。 教程中提到的韦东山老师的文章为我们提供了宝贵的学习资源,他的教程详细地阐述了如何从零开始编写BootLoader。参考文章中提供的链接,我们可以获得更加深入的技术细节和完整的代码实现。通过研究这些示例,开发者可以更加深入地理解Bootloader的设计原理和编程技巧,从而在实际项目中灵活运用。 Bootloader的编写需要对微控制器的硬件结构有深入的理解,包括对内存布局、中断管理、外设操作等各个方面的掌握。此外,编写Bootloader还需要具备一定的软件工程能力,如版本控制、错误处理、模块化设计等。这些技能的综合运用,将有助于开发者编写出稳定、高效、安全的Bootloader程序。 STM32F103C8T6是一款广泛应用于工业控制、消费电子等领域的微控制器,其优秀的性能和丰富的外设资源为开发者提供了良好的开发平台。而双区Bootloader则为STM32F103C8T6的应用程序更新提供了安全、便捷的解决方案,使得系统更加健壮,升级更加简单。 Bootloader在嵌入式系统中扮演着至关重要的角色,而基于STM32F103C8T6微控制器的双区Bootloader代码示例,不仅提供了一个实用的参考,还为开发者提供了深入学习和实践的机会,帮助他们更好地掌握Bootloader的设计和实现技术。
2025-08-22 13:58:48 616KB Bootloader
1
包含完整的客户端和服务器端,绝不像某些人分开上传多赚分数。本人认为极具参考价值。
2025-08-21 17:15:53 11KB Socket SocketAsyncEventArgs 异步Socket
1