我有基于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编程比较陌生,我的问题可能看起来很愚蠢......
答案 0 :(得分:0)
我想我看到了你的问题。当您的Analysis(字节,套接字)方法正在运行时,您的服务器无法接受更多连接。从客户端接受套接字后,在完成工作并再次调用.AcceptSocket()方法之前,您不再侦听该端口。
相反,您应该将工作发送到异步方法,并在绑定当前客户端连接后再次开始侦听。这是你想要做的一个很好的例子。