1

我正在编写一个客户端-服务器程序,其中客户端是 C++/winapi,服务器是 C#/.net。

客户端有一个从服务器读取的循环(并且可能会阻塞调用线程 [表示 t1] ,这对我来说很好)。它还有另一个线程 [表示 t2] ,等待一个超时的事件对象。

如果达到超时(并且事件尚未被单选),则 t2 线程将在同一个套接字上写入(准确地在字节上)。

我遇到的问题是,在 t1 上的读取返回之前,写入似乎不会返回(在某些合法的场景中它永远不会发生),就好像套接字不是全双工的。

PS:套接字是一个 AF_INET/SOCK_STREAM,我使用 Readfile 和 WriteFile 进行套接字 IO。

谢谢。

4

2 回答 2

0

我使用 WinSock 编程已有十多年了,我可以向您保证,套接字始终是全双工的。

唯一的方法WriteFile()(或send()WSASend())将阻塞调用线程任何时间是如果套接字以阻塞模式运行并且其等待传输的数据的出站队列已完全填满(队列的大小由SO_SNDBUF插座选项)。这表明另一方(您的 C# 服务器)没有从其套接字端点读取入站数据并及时确认接收到的数据,因此您的套接字端点可以从其出站队列中删除该数据,以便可以接受新数据进行传输。

如果您不想WriteFile()阻止您的呼叫,您可以:

  1. 启用SO_SNDTIMEO套接字选项以指定阻塞写入的超时时间。

  2. 在向套接字写入任何新内容之前,使用select()WSAAsyncSelect()WSAAsyncEvent()来检测套接字何时实际上是可写的(即,它何时可以接受数据而不阻塞)。

  3. 切换到非阻塞 I/O、异步重叠 I/O 或 I/O 完成端口。

于 2013-05-02T01:01:50.960 回答
0

不是 read() 和 write() 或 send() 和 recv() 的套接字都不是这样。你必须有一些你自己的同步。

于 2013-05-01T23:11:25.033 回答