下面是一个C#程序,演示了这个问题.
服务器开始侦听套接字.客户端连接到服务器,发送消息,使用Shutdown(SocketShutdown.Send)关闭其发送的一半连接,让服务器知道消息的结束位置,并等待服务器的响应.服务器读取消息,进行一些冗长的计算(这里使用睡眠调用进行模拟),向客户端发送消息,然后关闭连接.
在Windows上,客户端的接收呼叫总是在2分钟后失败,因为"连接尝试失败,因为连接方在一段时间后没有正确响应,或者建立的连接失败,因为连接的主机未能响应",即使超时是设置为无限.
如果我使用Mono在Linux中运行该程序,即使我将"冗长操作"设置为10分钟也不会发生超时,但是无论是使用Mono还是.NET运行它都会在Windows中发生.如果我将超时设置为1秒,则在1秒后超时.换句话说,它在我设置的超时或2分钟内超时,以较小者为准.
一个类似的示例程序,服务器向客户端发送消息,没有从客户端到服务器的消息,也没有半关闭,按预期工作,没有超时.
我可以通过修改我的协议来解决这个问题,以便在消息完成时使用其他一些指示服务器的方法(可能在消息前面加上消息的长度).但我想知道这里发生了什么.当超时设置为无限时,为什么Socket.Receive会在半闭连接上超时?
根据我的理解,只有半封闭发送的连接应该能够无限期地继续接收数据.在Windows的这个基本部分中似乎不太可能存在错误.难道我做错了什么?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Start server thread
Thread serverThread = new Thread(ServerStart);
serverThread.IsBackground = true;
serverThread.Start();
// Give the server some time to start listening
Thread.Sleep(2000);
ClientStart();
}
static int PortNumber = 8181;
static void ServerStart()
{
TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Any, PortNumber));
listener.Start();
while (true) …Run Code Online (Sandbox Code Playgroud)