- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在写一个监听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.
using
using(TcpClient client = obj as TcpClient){//DO SOMETHING}
关于c# - 服务停止后,后台线程仍在监听TCP端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50692409/
我是一名优秀的程序员,十分优秀!