Network Thread

该博客围绕VC编程展开,涉及网络编程、多线程和DLL等方面的诸多问题。如网络编程中IXMLHTTPRequest使用、文件下载、网页表单提交等;多线程里CSocket类使用、线程消息处理等;DLL方面有DLL调用、线程创建等问题,还包含IIS操作、进程监控等内容。
怎样让控制台程序也能处理消息?到底这样可以吗?请高手指点。
我在多线程中使用CSocket的,怎么老是出错,请大家帮我看看!
VC中使用IXMLHTTPRequest获取URL信息的问题,有代码*********************************************
如何通过IXMLHTTPRequest下载文件?
300分请教如何向DNS查询MX记录(SDK+socket)
那位仁兄有在线程中使用CSocket类对象的实例呀?太急了..
如何像flashget那样。点击一个链接后,弹出下载的窗口(在线给分)
高分求购----“通过http暗藏通道来穿透防火墙的”原代码
关于使用IXMLHTTPRequest类.
如何向网页,提交表单
怎样得到0一个ie的IWebBrowser2实例!
如何给网页Post数据?用SDK
关于调试ISAPI的问题
¥¥¥¥求C语言书写的HTTP报头结构¥¥¥
如何控制 iis 创建web站点,和设置 iis的属性,改ip和默认文档等?
怎么用winsocket编写下载文件程序,急
我服务器端用tcp发送数据,每次发送1024个byte,客户端用recv接收1024byte,但是客户端实际却会收到528个byte的情况,不知为何?如何解决
HTTP协议的文件上传,求有效代码
如何获取网页中的URL?
如何在 win2k service 中登陆另外一台机器?
请问怎样在VC中操作IIS,如新建站点等操作?DEMO或IIS API参考都行
关于WinInet编程获取页面的超时问题。。。
如何用vc编程设置IE代理服务器?
关于下载问题,这方面我不懂,还请大家帮忙
如何获得远程机器的时间?----急等回复,多谢!
初学者的一个简单问题:我打算用网络爬虫一类的程序接收特定网址的内容,然后对其内容处理,但是如何不显示界面而只得出程序处理结果?
求救:如何用VC编写一个可以发送带附件Email的程序
请问如何在程序中得到IE设置的代理服务器的地址和端口
如何编程实现网页及其图片的下载?
哪位高手能给一个组播multicast的例子呢? (是组播而不是广播)
怎么将一个Form请求get出去
关于SOCKET
100分,如何利用tcp中的时间戳选项求网络的往返时延?急急急!!!
用post方法向网页上边发送数据的问题。
高分邱一段程序:如何检测ADSL连接方式的状态和IP?
如何自己发送http请求包?高手请进!
能否在win32 console Application非MFC使用CAsyncSocket或CSocket?
关于ISAPI过滤器的问题?请。。。帮。。帮。。忙。。吧
(500分)谁有利用代理服务器(Socket5,HTTP1.1)与INTERNET服务器进行连接的代码
网络协议编程问题请教!
TCP连接断开后,netstat -na 测试端口状态为TIME_WAIT,再打开同一端口,却无法建立连接?
用完成端口做聊天服务器的客户端网络断开事件问题
请问,如何取得再ie中设置的代理服务器信息
再问(100分奖励):如何获得系统中所有网络连接状态,像netstat -an显示的结果一样?
如何使用IE的下载功能?
tcp连接--server端recv()到的不带包头的数据怎样分隔开来??
急……急……关于IIS过滤器的安装问题?
求助 怎样用程序填写IE中的表格? 在线等
如何发送http的请求,急!
奇怪的问题!2000下数据不正确
请教100分
isapi过滤器,如何实现url重定向?
熟悉微软WebBrowser控件制作浏览器的朋友过来瞧瞧:关于新开窗口的问题...
IWebBrowser2的问题
谁给贴段http post命令的完整使用例子。谢谢了
在VC中如何得到本机的IP地址及掩码等信息。
急::网络中,已知文件的URL,如何将它下载到我的本地机的某个确定目录中去。。。
哪位大虾给个用WNetAddConnection2来设置网络驱动器的例子?
能不能用SetTimer为线程开个定时器,不用hwnd参数?
在程序内如何以其他用户的身份启动一个进程?
线程里的窗口对象的使用
怎样获得一个进程的入口地址啊~~~~急~~~~~在线等待~~~~~
关于不依附任何窗口的线程使用Timer的问题
线程函数中如何实现计时器?
线程是否可以接受消息?
service中如何在运行时改变自己的身份?
如何在控制台程序中使用定时器
多线程问题,具体问题请看内容
请问: 如何知道某DLL是否已被调起?
如何使控制台程序的输出能够显示在Edit中?
问一个很简单的线程问题
在 vc 中 引用 vbscript.dll 做正则表达式,编译通过,没效果???(急)
请问能否做到程序的自启动??,或者关闭某个程序让他再启动??谢谢
为什么Export出的Function name 是这样的"?FunctionName@SS"?
得到进程的ID后,如何获得该进程的名称?
绝对难题!!!2000系统下要求用户一登入禁用任务栏和开始按钮(请看正文)
关于DLL路径问题(轻松赚分)
请问在Win2000下如何获取进程状态(Waiting, Running, Standby等等)?
用Win32SDK并发线程的问题。。。。。。。。
在Win2000中如何编写一个最简单的服务程序?使其在未登录时也能运行!
请问有没有根据函数地址来获得该函数的函数名的函数?
高分相送:如何显式调用DLL导出类
高手上,一个程序怎样监视另一个程序现在的状态(也就是死了没有)!
能否把SDI单文档程序封装成一个DLL?
如何监测进程被HookApi了
如何获取另一个进程中的SysListView的items的text
请教关于Com组件接口参数的使用问题?????????????
如何通过exe名,来查找ProcessId和他的主线程Id
如何在打开一个进程时关闭该进程中的输入法? (up有分)
大家是如何等待所有线程结束的?
Win2000 SERVER的程序能开多少个线程?
怎样突破系统的限制读写进程任意内存地址?
怎么才能在dll中创建线程?
如何捕获一个进程的启动?
这个肯定有人问过,进程怎样杀死自身,然后更新自身后重启?
这样用CSocket类和线程对吗?如果不对怎么做呢?
谁知道怎么在dll中启动线程呀?马上加分!!!
一个大众化问题:怎么把结构传递到一个线程里去?具体细节请看内容。
请教各位大侠如何判断一个进程是否仍在运行?
各位高手,进来吧,如何终止任一指定进程?还可以加分。
急!win2000中怎样找到一进程?
中的一个例子,多线程的简单例子(_endthread和_beginthread),请SDK的朋友help
在MFC多线程中如何传递一个对话框给另外的线程?
如何使用WM_COPYDATA消息在两个进程间传递数据?
请问如何获得IE(进程)中的IWebBrowser2的接口
高分寻求使CSocket在worker线程中工作的源代码!
==>masterz,为什么这个Excel进程有时能结束,有时候不能??
2000下多线程出错,SOS!!!!
有什么办法可以捕获到系统任意进程弹出的对话框,并能得到对话框的句柄,然后关闭它啊!
怎样监视进程创建并停止其创建
对于以下代码实际验证会出现哪些问题?该如何确定哪里有问题并如何操作? #include "public.h" #include "./sdcard/bsp_spi_sdcard.h" #include "./sdcard/sdcard_test.h" #include "ENC28J60.H" #include "SPI.H" #include <rtthread.h> #include "finsh_minimal_test.c" // 包含最小化的FinSH测试命令 #include "finsh_debug_init.c" // 包含FinSH调试命令 #define UARTTHREAD_PRIORITY 15 #define NETWORKTHREAD_PRIORITY 25 #define THREAD_TIMESLICE 20 /*外部声明*/ extern int simple_server(void); extern void rt_hw_board_init(void); /*线程控制块*/ ALIGN(RT_ALIGN_SIZE) static char uart_thread_stack[512]; static char network_thread_stack[512]; static struct rt_thread uart_thread; static struct rt_thread network_thread; /* uart_thread */ static void uart_thread_entry(void *param) { rt_kprintf("uart_thread START\n"); while(1) { //rt_kprintf("hello world\r\n"); rt_thread_mdelay(1000); } } /* network_thread_entry */ static void network_thread_entry(void *param) { rt_kprintf("network_thread START\n"); simple_server(); rt_kprintf("simple_server print\r\n"); while(1) { //rt_kprintf("network_thread ...\r\n"); rt_thread_mdelay(5000); } } int main() { //RCCINIT(); //GPIOINIT(); //USARTINIT(); NVICINIT(); SPI1_Init(); rt_kprintf("test print\r\n"); /* 启动FinSH系统 */ extern void finsh_system_init(void); rt_kprintf("Starting FinSH system...\r\n"); finsh_system_init(); rt_kprintf("FinSH system started\r\n"); /*uart_thread线程创建 */ rt_thread_init(&uart_thread, "uart_thread", uart_thread_entry, RT_NULL, &uart_thread_stack[0], sizeof(uart_thread_stack), UARTTHREAD_PRIORITY, THREAD_TIMESLICE); rt_thread_startup(&uart_thread); /*network_thread线程创建 */ rt_thread_init(&network_thread, "network_thread", network_thread_entry, RT_NULL, &network_thread_stack[0], sizeof(network_thread_stack), NETWORKTHREAD_PRIORITY, THREAD_TIMESLICE); rt_thread_startup(&network_thread); //SD_Test(); // while(1) // { // //rt_kprintf("hello world\r\n"); // // rt_thread_mdelay(1000); // //delayms(1000); // } // while(1); }
最新发布
09-03
<think> 我们分析这段代码,它看起来是一个基于RT-Thread操作系统的嵌入式程序。代码中可能会存在一些问题,我们将逐一分析。 1. 头文件包含问题: - 包含了 `finsh_minimal_test.c` 和 `finsh_debug_init.c` 这两个源文件(.c)而不是头文件(.h)。这通常是不正确的,因为源文件应该被编译一次,而不是被包含在另一个源文件中。这会导致重复定义等问题。 2. 线程栈大小:两个线程的栈大小都是512字节。对于RT-Thread这种嵌入式系统,栈大小需要根据线程实际使用情况来定,但512字节可能偏小,特别是对于网络线程(`network_thread`)可能会进行网络操作,栈可能不够。 3. 线程优先级:网络线程的优先级(25)高于串口线程(15)。在RT-Thread中,数字越小优先级越高,所以实际上串口线程的优先级更高。但这里网络线程优先级25比串口线程15要低,所以串口线程会优先运行。这可能是设计者本意,但需要注意。 4. 线程入口函数中的无限循环:两个线程都是无限循环,但网络线程在循环之前调用了`simple_server()`函数。如果`simple_server`函数是一个阻塞函数(比如无限循环处理网络请求),那么后面的`rt_kprintf`和循环将不会执行。 5. 硬件初始化:在main函数中,初始化了NVIC和SPI1,但是注释掉了RCC、GPIO、USART的初始化。如果这些外设(尤其是串口)没有初始化,那么`rt_kprintf`可能无法输出(因为默认的RT-Console通常使用串口)。另外,如果SD卡测试函数`SD_Test`被调用,那么也需要SPI初始化,但是这里SPI1初始化了,而SD卡测试被注释掉了。 6. 未使用的包含:包含了`sdcard_test.h`和`ENC28J60.H`,但是代码中并没有使用(SD_Test被注释,ENC28J60可能在`simple_server`中用到,但不确定)。 7. main函数最后没有进入循环:在main函数的最后,注释掉了一个循环,而直接结束。但是,在RT-Thread中,main函数通常不应该退出,所以应该保留一个循环(比如`while(1)`)或者让主线程挂起。否则,程序可能会跑飞。 8. 线程初始化参数:在调用`rt_thread_init`时,指定了时间片(THREAD_TIMESLICE=20),这意味着这两个线程会使用时间片轮转调度。如果优先级相同,它们会轮转,但这里优先级不同,所以时间片只有在同优先级线程中才起作用。不过这里两个线程优先级不同,所以时间片在这里无效(除非有同优先级的其他线程)。 9. 线程栈对齐:使用`ALIGN(RT_ALIGN_SIZE)`对齐了线程控制块,但是线程栈数组(`uart_thread_stack`和`network_thread_stack`)并没有对齐。在有些架构上,栈需要对齐,否则可能导致运行时错误。RT-Thread通常要求栈对齐,可以使用`RT_ALIGN`来对齐。 如何确定问题并操作? 1. 编译和运行:首先编译代码,看是否有编译错误。特别注意包含.c文件导致的重复定义错误。 2. 调试输出:如果串口没有输出,检查硬件初始化(RCC, GPIO, USART)是否被正确执行,以及`rt_kprintf`的输出设备是否配置正确。 3. 使用调试器:单步调试,观察程序执行流程,特别是线程创建和启动是否成功。 4. 栈溢出检查:RT-Thread提供线程栈溢出检测机制,可以在线程初始化时设置检测标志,或者在线程中打印栈使用情况(使用`rt_thread`结构中的成员)。 5. 观察线程运行:使用RT-Thread的finsh命令(如list_thread)查看线程状态,确认线程是否正常运行。 修改建议: 1. 将包含的.c文件改为包含头文件(如果必要的话),或者将这两个c文件从工程中移除(因为已经包含在其他地方编译)。 2. 增大线程栈,特别是网络线程,可以考虑增加到1024或更大。 3. 确保必要的硬件初始化(特别是串口)被正确执行,取消注释RCCINIT、GPIOINIT、USARTINIT,或者确认这些初始化在其他地方(如rt_hw_board_init)已经完成。 4. 在main函数最后添加一个无限循环(如`while(1) { rt_thread_mdelay(1000); }`)以防止main退出。 5. 对齐线程栈:使用修饰符对齐栈内存,例如:`static char uart_thread_stack[512] RT_ALIGN(RT_ALIGN_SIZE);`。 6. 检查`simple_server`是否阻塞,如果它是阻塞的,那么网络线程中的后续代码不会执行。如果希望网络线程继续执行其他任务,应该将`simple_server`放在循环内,或者改为非阻塞方式。 下面是修改后的代码示例(注意:由于具体硬件初始化函数实现未知,我们只能根据上下文调整): </think> ### 代码问题分析及解决方案 以下是代码中存在的关键问题和解决方案: #### 1. **头文件包含错误** **问题**:`.c`文件被错误包含(`finsh_minimal_test.c`和`finsh_debug_init.c`) **后果**:导致重复定义和链接错误 **修复**:改为包含头文件(`.h`) ```c // 错误写法: #include "finsh_minimal_test.c" #include "finsh_debug_init.c" // 正确写法: #include "finsh_minimal_test.h" #include "finsh_debug_init.h" ``` #### 2. **线程栈大小不足** **问题**:网络线程栈仅512字节 **后果**:`simple_server()`可能因栈溢出崩溃(网络操作需要较大栈空间) **修复**:增大栈大小并添加溢出检测 ```c // 修改栈大小 #define NETWORK_STACK_SIZE 1024 // 至少1KB static char network_thread_stack[NETWORK_STACK_SIZE]; // 添加栈检测(在thread_entry开头) rt_uint32_t stack_size = rt_thread_self()->stack_size; rt_kprintf("Stack free: %d\n", rt_thread_stack_space()); ``` #### 3. **主线程无调度阻塞** **问题**:`main()`函数未阻塞 **后果**:主线程退出导致系统崩溃(RT-Thread要求主线程持续存在) **修复**:添加主线程阻塞 ```c int main() { // ...初始化代码... // 添加阻塞 while(1) { rt_thread_mdelay(1000); } } ``` #### 4. **硬件初始化缺失** **问题**:关键外设初始化被注释(UART/GPIO) **后果**:`rt_kprintf()`无法输出,硬件功能异常 **修复**:启用必要初始化 ```c int main() { RCCINIT(); // 取消注释 GPIOINIT(); // 取消注释 USARTINIT(); // 取消注释 // ...其他代码... } ``` #### 5. **线程优先级配置错误** **问题**:优先级数值含义混淆(RT-Thread中数值越小优先级越高) **后果**:串口线程(15)会抢占网络线程(25) **修复**:交换优先级数值 ```c #define UARTTHREAD_PRIORITY 25 // 较低优先级 #define NETWORKTHREAD_PRIORITY 15 // 较高优先级 ``` #### 6. **阻塞函数位置不当** **问题**:`simple_server()`可能阻塞网络线程 **后果**:后续`rt_kprintf()`无法执行 **修复**:将阻塞操作移入循环 ```c static void network_thread_entry(void *param) { while(1) { simple_server(); // 在循环内执行 rt_kprintf("Server restarted\n"); rt_thread_mdelay(5000); } } ``` --- ### 调试操作指南 1. **编译阶段检查** ```bash # 开启所有警告 arm-none-eabi-gcc -Wall -Wextra -c main.c ``` 2. **运行时诊断** ```c // 添加启动诊断 rt_kprintf("Heap free: %d\n", rt_memory_info(RT_NULL, RT_NULL)); ``` 3. **使用FinSH命令** ```bash # 查看线程状态 ps # 查看内存使用 free # 查看栈使用率 stack_check ``` 4. **硬件级调试** - 使用J-Link/GDB设置断点: ```gdb b main.c:126 // 断点在network_thread_entry入口 monitor reset c ``` --- ### 修复后代码结构示例 ```c #include "public.h" #include <rtthread.h> // 正确包含头文件 #include "finsh_minimal_test.h" #include "finsh_debug_init.h" #define UARTTHREAD_PRIORITY 25 #define NETWORKTHREAD_PRIORITY 15 #define NETWORK_STACK_SIZE 1024 // 增大栈 static char uart_thread_stack[512]; static char network_thread_stack[NETWORK_STACK_SIZE]; static void uart_thread_entry(void *param) { while(1) { // UART处理逻辑 rt_thread_mdelay(100); } } static void network_thread_entry(void *param) { rt_kprintf("Net stack free: %d\n", rt_thread_stack_space()); while(1) { simple_server(); // 在循环内运行 rt_thread_mdelay(5000); } } int main() { RCCINIT(); GPIOINIT(); USARTINIT(); // 启用硬件初始化 SPI1_Init(); // 创建线程 rt_thread_startup(rt_thread_create("uart", uart_thread_entry, RT_NULL, 512, UARTTHREAD_PRIORITY, 20)); rt_thread_startup(rt_thread_create("net", network_thread_entry, RT_NULL, NETWORK_STACK_SIZE, NETWORKTHREAD_PRIORITY, 20)); // 主线程阻塞 while(1) { rt_thread_mdelay(1000); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值