那些与.Net广泛合作以创建客户端/服务器应用程序的人的问题。
我已将一个涉及服务器和客户端应用程序的简单测试放在一起进行负载测试。客户端在并行循环中与我的服务器建立500个连接,并侦听传入的消息。服务器接受每个连接,为每个连接创建一个连接对象,每个触发一个250ms的定时器,通过网络流发送5000个字节。非常简单的东西。
然而,它很快就会出现错误和崩溃。遇到麻烦的第一个迹象是其中一个客户端连接: SocketException:无法建立连接,因为目标计算机主动拒绝了
收到的第二个错误通常是服务器端,尝试在NetworkStream.Write
期间发送失败。
System.Net.Sockets.SocketException:'现有连接被远程主机强行关闭'
我的问题是:我的服务器只是将数据连续写入与套接字关联的一组网络流,并且在一定数量的套接字(客户端连接)之后,这似乎已经消失了。有人知道为什么或适用于此处的任何限制吗?
正在一台功能强大的机器上进行测试。值得注意的是,在100个连接处,它可以工作更长时间而不会出错。
服务器和客户端代码的关键部分如下。
客户端:
Parallel.For(1, 500, i =>
{
var c = new ConnectedClient(i);
c.Connect();
});
public void Connect()
{
_tcp = new TcpClient("192.168.255.103", 666);
_tcp.ReceiveTimeout = 1000;
_tcp.SendTimeout = 1000;
_tcp.SendBufferSize = sendBufferSize;
_tcp.NoDelay = true;
_netStrm = _tcp.GetStream();
_netStrm?.BeginRead(_byReceived, 0, 8192, DataReceived, null);
}
private void DataReceived(IAsyncResult ar)
{
// this code receives the data, pretty boilerplate
}
在服务器上:
_tcpServer = new TcpServer(666, "Server");
_tcpServer.ClientConnected += TcpServerClientConnected;
private void TcpServerClientConnected(object sender, TcpClientConnectedEventArgs e)
{
var newClient = new ConnectedClient();
newClient.Open(e.Client);
}
public void Open(TcpClient tcpClient)
{
_tcp = tcpclient;
_tcp.ReceiveTimeout = 1000;
_tcp.SendTimeout = 1000;
_tcp.SendBufferSize = sendBufferSize;
_tcp.NoDelay = true;
_messageSend = new Timer(250);
_messageSend.Elapsed += MessageSendOnElapsed;
_netStrm = _tcp.GetStream();
_netStrm?.BeginRead(_byReceived, 0, ReceiveBufferSize, DataReceived, null);
}
private void MessageSendOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
{
var data = new byte[5000];
var packetLength = BitConverter.GetBytes((int)5000);
using (var mem = new MemoryStream())
{
mem.Write(packetLength, 0, packetLength.Length);
mem.Write(data, 0, data.Length);
_netStrm.Write(mem.ToArray(), 0, Convert.ToInt32(mem.Length));
}
}
为了那些提问的好处,如果可以从同一台机器进入服务器的多个连接,这是在网络流写入之前的Console.WriteLine的输出:
Console.WriteLine($"sending from {_tcp.Client.LocalEndPoint} to {_tcp.Client.RemoteEndPoint}");
sending from 192.168.255.103:666 to 192.168.255.103:37307
sending from 192.168.255.103:666 to 192.168.255.103:37300
sending from 192.168.255.103:666 to 192.168.255.103:37186
sending from 192.168.255.103:666 to 192.168.255.103:37187
sending from 192.168.255.103:666 to 192.168.255.103:37305
sending from 192.168.255.103:666 to 192.168.255.103:37178
sending from 192.168.255.103:666 to 192.168.255.103:37184
sending from 192.168.255.103:666 to 192.168.255.103:37180
sending from 192.168.255.103:666 to 192.168.255.103:37296
sending from 192.168.255.103:666 to 192.168.255.103:37183
sending from 192.168.255.103:666 to 192.168.255.103:37297
sending from 192.168.255.103:666 to 192.168.255.103:37190
sending from 192.168.255.103:666 to 192.168.255.103:37175
sending from 192.168.255.103:666 to 192.168.255.103:37298
sending from 192.168.255.103:666 to 192.168.255.103:37185
sending from 192.168.255.103:666 to 192.168.255.103:37193
sending from 192.168.255.103:666 to 192.168.255.103:37173
sending from 192.168.255.103:666 to 192.168.255.103:37182
sending from 192.168.255.103:666 to 192.168.255.103:37174
sending from 192.168.255.103:666 to 192.168.255.103:37166
sending from 192.168.255.103:666 to 192.168.255.103:37168
sending from 192.168.255.103:666 to 192.168.255.103:37176
您将看到上面短暂的本地客户端端口(37176等)