我有基于 C# 的 Windows 服务,它使用 TCP 端口通过 Web 连接到多个客户端。服务器具有静态 IP,可帮助客户端定位服务器。我已经在这里发布了代码。
TcpListener tcp = new TcpListener(ipAddr, portNo);
tcp.Start();
listening = true;
while (listening)
{
Socket mySocket = null;
// Blocks until a client has connected to the server
try
{
mySocket = tcp.AcceptSocket();
Thread.Sleep(500);
byte[] bReceive = new byte[1024 * 1024 * 2];
int i = mySocket.Receive(bReceive);
byte[] databyte = new byte[i];
for (int j = 0; j < i; j++)
{
databyte[j] = bReceive[j];
}
Analysis(databyte, mySocket);
}
catch (Exception exc)
{
logger.Error(exc);
}
}
listening = false;
tcp.Stop();
有时我会遇到这两个错误之一,即关闭连接并且所有客户端都断开连接:System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags).
System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
这些错误不是周期性的,而是会导致所有客户端在出现时断开连接。该服务连接到大约 300 个客户端。
编辑 1:
根据@Sean H 的建议,我修改了代码以异步读取数据。以下是代码:
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static Logger logger = LogManager.GetCurrentClassLogger();
//constructor
public Server()
{
listener.Bind(new IPEndPoint(IPAddress.Parse("192.168.1.5"), 9000));
listener.Listen(300);
listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
//Console.Write("Server Running...\r\n");
}
public void OnConnectRequest(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket accepted = listener.EndAccept(ar);
listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
NewConnection(accepted);
}
//send a string message over a TCP socket
public void sendMSG(Byte[] bSendData, ref Socket mySocket)
{
//some code which sends data according to my protocol
int numBytes = 0;
try
{
if (mySocket.Connected)
{
if ((numBytes = mySocket.Send(bSendData, bSendData.Length, 0)) == -1)
{
logger.Error("Socket Error: Cannot Send Packet (Custom Error by me)");
}
else
{
}
}
else
{
logger.Error("Link Failed - Socket closed (Custom Error by me)");
}
}
catch (Exception exc)
{
logger.Error(exc);
}
}
public void receiveMSG(ref Socket mySocket)
{
byte[] bReceive = new byte[1024 * 1024 * 2];
int i = mySocket.Receive(bReceive);
byte[] databyte = new byte[i];
for (int j = 0; j < i; j++)
{
databyte[j] = bReceive[j];
}
Analysis(databyte, mySocket);
}
//function called whenever a NEW CLIENT is connected
public void NewConnection(Socket sockClient)
{
//Console.WriteLine("user {0} has joined", sockClient.RemoteEndPoint);
//byte[] msg = new byte[20];
receiveMSG(ref sockClient);
//sockClient.Receive(msg);
}
这在测试环境中效果很好。我还没有将它部署在生产环境中,原因是服务器如何知道它收到的数据是否已完成,或者还有一部分字符串仍需从客户端传输到服务器。在将 Windows 服务部署到生产环境之前,我无法知道它的实际行为,因为我在测试环境中有 4 个客户端,而在生产环境中有 300 个客户端。
但是@Sean H 的建议变得很棒,因为现在服务器不会被阻塞,直到处理来自客户端的请求。它正在同时收听多个客户。
我对这种 TCP/IP 编程比较陌生,我的问题可能看起来很愚蠢......
最佳答案
我想我看到了你的问题。当您的 Analysis(byte, Socket) 方法正在运行时,您的服务器无法接受更多连接。一旦您接受来自客户端的套接字,您将不再监听该端口,直到您完成工作并再次调用 .AcceptSocket() 方法。
相反,您应该将工作启动到异步方法,并在绑定(bind)当前客户端连接后再次开始监听。这是您想要做的一个很好的例子。
https://docs.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example
关于c# - C# 中的远程主机强制关闭现有连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46910267/