【发布时间】:2019-01-02 01:18:33
【问题描述】:
我的申请有问题, 我有一个 TCPListener,比如说在端口 14000 上监听 关闭应用程序后,我可以在 CMD 上看到侦听器仍在侦听。 在应用程序的第二次运行时,我无法在同一个端口(14000)上启动监听器,因为它已经被占用了,我在第二次运行时将应用程序端口更改为 15000,工作得很好,监听器在应用程序正在关闭, 我假设在第一次运行时,端口 14000 上的第一个侦听器在应用程序死后保持打开状态,在第二次运行时,应用程序很好地关闭/打开端口 15000 上的侦听器,为什么会发生这种情况?我想可能是关于端口 14000 我已经切换了打开端口的顺序(首先打开了 15000)并看到 15000 保持打开状态并且 14000(第二次运行)关闭并正确打开,为什么在第一次运行听众没有被关闭?? 我的服务器的代码:
class Server : IDisposable
{
private const int TIMER_PERIOD = 60 * 1000; // ms
private string servePort;
private string serverIP;
byte[] DataReceived = new byte[1024];
Action<string> MssageReceiveCallback;
private bool isListening = false;
static Timer serverTimer = null;
private TcpListener _Server;
private Dictionary<int, TcpClient> clientsList = new Dictionary<int, TcpClient>();
private bool serverListening = true;
private static int ClientInstance = 0;
public Server(string _serverIP, string _serverPORT, Action<string> messageReceiveCallback)
{
serverIP = _serverIP;
servePort = _serverPORT;
MssageReceiveCallback = messageReceiveCallback;
// InitilizeServer();
}
private void InitilizeServer()
{
_Server = new TcpListener(IPAddress.Parse(serverIP), int.Parse(servePort));
// if (serverTimer == null)
// serverTimer = new Timer(new TimerCallback(OnTimerCallback), null, TIMER_PERIOD, TIMER_PERIOD);
Task.Run(() =>
{
try
{
_Server.Start();
while (_Server != null)
{
TcpClient tcpClient;
try
{
tcpClient = _Server.AcceptTcpClient();
}
catch
{
continue;
}
Task.Run(() =>
{
ClientInstance++;
int currentinstance = ClientInstance;
clientsList.Add(currentinstance, tcpClient);
try
{
while (tcpClient.Connected && serverListening)
{
if (tcpClient.GetStream().DataAvailable)
{
int actualBufferlength = tcpClient.GetStream().Read(DataReceived, 0, DataReceived.Length);
byte[] data = new byte[actualBufferlength];
Buffer.BlockCopy(DataReceived, 0, data, 0, actualBufferlength);
string asciiMessage = Encoding.ASCII.GetString(data);
MssageReceiveCallback(asciiMessage);
}
else
{
Thread.Sleep(5);
}
}
}
catch (Exception ex)
{
}
finally
{
clientsList[currentinstance].Close();
clientsList.Remove(currentinstance);
}
});
}
}
catch (Exception ex)
{
}
});
}
public void StartServer()
{
InitilizeServer();
isListening = true;
}
public void SendMessage(string msg)
{
byte[] data = ASCIIEncoding.ASCII.GetBytes(msg);
foreach (TcpClient client in clientsList.Values)
{
client.GetStream().Write(data, 0, data.Length);
}
}
public void Dispose()
{
serverListening = false;
foreach (var item in clientsList.Values)
{
if (item.Connected)
item.Close();
}
_Server.Server.Close();
}
}
更新: 我检查了 TCPView 以查看侦听器绑定到哪个应用程序并找到了这个:
看起来监听器可用于不存在的进程
【问题讨论】:
-
是的,正如您在 Dispose 方法中看到的那样,我正在执行 _Server.Server.Close() 此外,在第二次运行时正确关闭时它没有停止是没有意义的
-
这里有许多问题可能都会导致问题,但我不能指出一个并说“就是这样”。一个问题是您的
clientsList集合不是线程安全的,并且(另外)您可能正在清除它,而另一个线程正在接受新连接,因为您没有关闭关闭侦听器,直到 您尝试清除该集合。 -
Close还需要发生一些网络活动,因此如果您调用Close然后您的进程立即退出,它可能没有时间清理所有内容。 -
不幸的是它没有用@Damien_The_Unbeliever
-
您认为我在提供答案?我指出了一些应该解决的问题。如果我相信他们会解决您的问题,我会提供答案,而不是评论。
标签: c# networking tcp port tcplistener