gpt4 book ai didi

c# - 服务停止后,后台线程仍在监听TCP端口

转载 作者:行者123 更新时间:2023-12-03 11:10:45 26 4
gpt4 key购买 nike

我正在写一个监听TCP端口的C#服务(.NET 4.0)。我在后台线程(使用任务并行库)上启动TcpListener,因此该服务不会对Windows无响应。每当有客户端连接时,我也会使用TPL,因为每个客户端都会做一些数据库工作,并且我不想阻止其他客户端。

我在Windows Server 2012 R2 Standard上使用InstallUtil.exe安装和卸载服务。每当我停止服务并卸载它时,使用netstat -abo可以看到[System]进程仍在监听该端口。它有一个PID,但是在任务管理器或任务列表中看不到带有此PID的进程,也无法使用taskkill杀死它。它只是说没有找到进程,但是当我运行netstat -abo时它总是存在的。如果尝试使用同一端口再次启动服务,则会收到套接字异常:

Only one usage of each socket address (protocol/network address/port) is normally permitted
Stacktrace:
at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.Bind(EndPoint localEP)
at System.Net.Sockets.TcpListener.Start(Int32 backlog)

我猜我的后台线程在停止服务后仍在徘徊,但我不知道现在如何杀死它们,以及如何防止这种情况发生。我希望这里是相关的代码(删除的异常处理和日志记录以便于阅读):
public partial class MyService : ServiceBase
{
private static TCPServer server = null;

protected override void OnStart(string[] args)
{
server = new TCPServer();
}

protected override void OnStop()
{
if (server != null)
{
server.StopServer();
}
}
}

class TCPServer
{
public static TcpListener listener = null;
private static Task listenerTask = null;
private static List<Task> clientTasks = new List<Task>();

public TCPServer()
{
listenerTask = new Task(() => StartServer());
listenerTask.Start();
}

public void StopServer()
{
foreach(Task task in clientTasks)
{
task.Dispose();
}

listenerTask.Dispose();

if (listener != null)
{
listener.Stop();
listener = null;
}
}

private void StartServer()
{
Int32 port = 51987;
IPAddress localAddr = GetLocalIP();

listener = new TcpListener(localAddr, port);
listener.Start();

while (listener != null)
{
if (listener.Pending())
{
TcpClient client = listener.AcceptTcpClient();

Task task = new Task((obj) => ProcessClient(obj), client);
task.Start();
clientTasks.Add(task);
}
}
}

private void ProcessClient(object obj)
{
using (TcpClient client = obj as TcpClient)
{

Byte[] bytes = new Byte[2048];
String data = null;

NetworkStream stream = client.GetStream();
int i;

while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
data = Encoding.ASCII.GetString(bytes, 0, i);
}

// do some stuff with data
// If an exception is thrown here, the rogue thread issue happens when I stop the service.
// Otherwise, everything is good - I stop the service and no rogue thread, I can reuse the listener port.
}
}
}

编辑:
使用建议的更改更新了代码。我还发现,仅当在我的一个客户端线程中引发异常时,才会出现此流氓线程问题。如果一切正常,则停止服务时没有恶意线程。

最佳答案

在这种情况下,“停止”方法意味着停止当前连接并开始监听新的连接,因此请确保您的客户端正确关闭,从而不会创建新的连接。

The Stop method also closes the underlying Socket and creates a newSocket for the TcpListener. If you set any properties on theunderlying Socket prior to calling the Stop method, those propertieswill not carry over to the new Socket.


https://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.stop(v=vs.110).aspx#
此外,请确保您在客户端上使用 using
using(TcpClient client = obj as TcpClient){//DO SOMETHING}

关于c# - 服务停止后,后台线程仍在监听TCP端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50692409/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com