【发布时间】:2017-08-13 11:50:39
【问题描述】:
尊敬的 Stack Overflow 社区,
我目前正在用 C# 开发一个在线 TCG。服务器在我自己的机器上运行得非常好(四核,八线程 Windows 7)。我可以毫无问题地连接 12 个客户端。但是当我在服务器上启动它时,客户端的最大数量变得受限于机器上处理器核心的数量。我在单核 Windows 2016 Server 上运行代码,无法连接多个客户端来启动游戏。然后我在四核 Windows 2012 Server 上运行服务器,只能连接四个客户端并启动两个游戏。在有人断开连接之前,任何进一步的客户都会被完全忽略。然后新客户端被接受,服务器崩溃。
服务器是带有 .NET Framework 4.0 的 MS Visual Studio 2015 Windows 窗体应用程序。 Windows Server 机器具有 .NET Framework 4.0,而我自己的机器具有 4.5 版本。
我很乐意提供您可能需要的任何其他信息并回答您的所有问题。
C# 中的服务器代码:
public void Init()
{
try {
server = new TcpListener(IPAddress.Any, port);
server.Start();
serverRunning = true;
server.BeginAcceptTcpClient(AcceptTcpClient, server);
OutputTB.Text = "server has been started on port " + port.ToString();
}
catch (Exception e) {
OutputTB.Text = "socket error: " + e.Message;
}
}
private void AcceptTcpClient(IAsyncResult newClient)
{
if (!serverRunning)
return;
server.BeginAcceptTcpClient(AcceptTcpClient, server);
TcpListener listener = (TcpListener)newClient.AsyncState;
ServerClient client = new ServerClient(listener.EndAcceptTcpClient(newClient));
Send("SWHO", client);
connectedClients.Add(client);
Invoke((MethodInvoker)delegate {
ClientListBox.Items.Add("Waiting for authentification...");
});
NetworkStream stream = client.tcp.GetStream();
StreamReader reader = new StreamReader(stream, true);
while (client.connected && serverRunning) {
if (stream.DataAvailable) {
string data = reader.ReadLine();
if (data != null)
OnIncomingData(client, data);
}
}
Invoke((MethodInvoker)delegate {
if (client.authenticated)
ClientListBox.Items.Remove(client.playerName);
else
ClientListBox.Items.Remove("Waiting for authentification...");
});
Send("SDISC", client);
waitingClients.Remove(client);
connectedClients.Remove(client);
client.tcp.Close();
}
private void OnIncomingData()
{
//process client data
}
【问题讨论】:
-
我会从 AcceptTcpClient() 中提取身份验证部分。也许它无法释放线程,直到回调返回或其他东西。接受连接并离开那里。也许使用状态机或其他东西来表明您正在等待客户端进行身份验证,以便下次读取数据时,您知道如何处理它。
-
您能否将其简化为仅接受连接的服务器而不接受其他任何内容(这样它仍然可以重现)?这将简化问题。顺便说一句,您是否重新配置了线程池?这有点线程池耗尽的味道,这是不寻常的(也是一个错误)。
标签: c# .net server tcplistener