返回

WSAPoll无法读取stdin的终极解决指南

windows

Windows 下 WSAPoll 无法读取 stdin 的全面解决指南

问题

当从 Linux 将 C 源代码移植到 Windows 时,你可能遇到 stdin 永远不会就绪的问题。这会导致 WSAPoll 阻塞代码,因为它缺少就绪的文件符。本文旨在提供一个全面的指南,以解决此问题。

使用 WSAAsyncSelect

在 Windows 中,WSAPoll 仅适用于套接字,而不适用于管道(如 stdin)。要解决此问题,可以使用 WSAAsyncSelect 函数,它允许你异步接收来自管道(如 stdin)的事件。

  1. 建立关联: 使用 WSAAsyncSelectstdin 接收事件的窗口句柄关联起来。
  2. 处理消息: 在你的 Windows 应用程序中,处理 stdin 接收事件的消息。
  3. 停止通知: 当不再需要异步接收 stdin 事件时,使用 WSAAsyncSelect 取消异步通知。

修改事件循环

start_event_loop 函数中,将 poll 替换为 WaitForMultipleObjects

  1. 等待事件: 使用 WaitForMultipleObjects 等待套接字或 stdin 事件。
  2. 检查索引: 验证返回的索引是否正确匹配 TCP 套接字文件描述符。
  3. 验证事件类型: 确保套接字事件是 FD_READ 事件。

解决 WaitForMultipleObjects 问题

确认套接字事件: 使用 Wireshark 捕获数据包,以确保套接字事件实际被发送。
检查传入索引: 确保 WaitForMultipleObjects 返回的索引匹配 TCP 套接字文件描述符。
验证事件类型: 确保套接字事件是 FD_READ 事件。
排除其他事件: 确保没有其他事件干扰 WaitForMultipleObjects 的调用。
调试和日志记录: 添加调试输出和日志记录,以跟踪事件的处理情况。

结论

通过遵循这些步骤,你应该能够解决 Windows 下使用 WSAPoll 无法读取 stdin 的问题。通过使用 WSAAsyncSelect 和修改事件循环,你可以确保 stdinWaitForMultipleObjects 中正常触发。

常见问题解答

  1. 为什么我无法在 Windows 中使用 WSAPoll 读取 stdin

WSAPoll 在 Windows 中仅适用于套接字,而不适用于管道(如 stdin)。

  1. 如何处理 stdin 事件?

使用 WSAAsyncSelectstdin 接收事件的窗口句柄关联起来,并在你的 Windows 应用程序中处理 WM_USER + 1 消息。

  1. 为什么我的 WaitForMultipleObjects 返回错误索引?

请检查 TCP 套接字文件描述符是否正确分配给数组。

  1. 如何排除其他事件?

确保没有其他事件注册,例如键盘输入,这些事件可能会干扰 WaitForMultipleObjects

  1. 调试和日志记录有什么用?

调试输出和日志记录有助于跟踪事件处理情况,并识别任何潜在问题。