动态更改 TCPClient 端口
假设您有以下代码。
this._tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this._tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCommunication));
clientThread.Start(client);
}
private void HandleClientCommunication(object client)
{
using (TcpClient tcpClient = (TcpClient) client)
{
//Do my work
}
}
这种实现的问题是,我在初始连接中使用的任何端口都会在客户端通信中使用,因此(尽管 tcpListener 仍在侦听,但在端口被释放之前,它将无法接受其他连接) 。
那么有没有办法告诉 tcpClient 更改它正在使用的端口,或者是通过向客户端发回新端口号并告诉它重新连接来实现此类功能的唯一方法?
IE:
TcpListener1.AcceptTcpClient(); //Wait
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCommunication));
clientThread.Start(client);
private void HandleClientCommunication(object client)
{
using (TcpClient tcpClient = (TcpClient) client)
{
//Generate random port number send back to client and create another thread with a new tcpListener and wait again?
}
}
从代码来看, 客户端的本地端点和 服务器的远程端点 似乎更改为不同的端口 但每种情况下的逆仍然是 相同的。
IE:
Started server tcpListener on 121
ClientLocalEndPoint: {127.0.0.1:1380}
ClientRemoteEndPoint: {127.0.0.1:121}
ServerLocalEndPoint: {127.0.0.1:121}
ServerRemoteEndPoint: {127.0.0.1:1380}
Lets say you having the following code.
this._tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this._tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCommunication));
clientThread.Start(client);
}
private void HandleClientCommunication(object client)
{
using (TcpClient tcpClient = (TcpClient) client)
{
//Do my work
}
}
The problem with such an implementation is that whatever port I have used in the initial connection is then used in the client communication and therefor (despite the fact that the tcpListener is still listening it will be unable to accept other connections till the port is freed).
So is there someway to tell the tcpClient to change the port it is working on or is the only way to implement such functionality by sending back the client a new port number and telling it to reconnect?
IE:
TcpListener1.AcceptTcpClient(); //Wait
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientCommunication));
clientThread.Start(client);
private void HandleClientCommunication(object client)
{
using (TcpClient tcpClient = (TcpClient) client)
{
//Generate random port number send back to client and create another thread with a new tcpListener and wait again?
}
}
Looking at the code it appears that
the localendpoint for the client and
the remoteendpoint for the server
appears to change to a different port
yet the inverse in each case stays the
same.
IE:
Started server tcpListener on 121
ClientLocalEndPoint: {127.0.0.1:1380}
ClientRemoteEndPoint: {127.0.0.1:121}
ServerLocalEndPoint: {127.0.0.1:121}
ServerRemoteEndPoint: {127.0.0.1:1380}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你对这里的问题的理解是错误的;生成一个新线程来处理
TcpClient
,然后循环回TcpListener.AcceptTcpClient()
并不需要您更改端口;单个服务器可以将多个连接连接到同一套接字。否则,网络服务器如何同时处理多个用户?
您的代码在某处出现了其他问题。您的“每个连接一个线程”代码并不理想(每个连接一个线程远远超出了需要),但它是一种快速而肮脏的方式,效果很好。
您如何构建监听器?你在和客户做什么?后续连接到底发生了什么?
You are incorrect about the problem here; Spawning a new thread to handle the
TcpClient
and then looping back toTcpListener.AcceptTcpClient()
does not require you to change ports; A single server can get multiple connections in to the same socket.Otherwise, how would web servers handle multiple users at once?
Something else is going wrong with your code somewhere. Your "thread-per-connection" code is not ideal (a thread per connection is much more than is needed), but it is a quick-and-dirty way that works just fine.
How are you constructing the Listener? What are you doing with the client? And what exactly is happening to subsequent connections?
我同意其他人的观点,您可能希望查看异步方法,而不是为每个连接使用单独的线程,或者至少是BackgroundWorker...至于发生的情况,您是否尝试调试以确保有一个线程卡在 AcceptTcpClient 上称呼?您可以尝试在 Start() 调用中指定高积压。它是否可能是具有范围的东西,并且可能是线程的垃圾收集,因为您没有维护它的引用?如果将 Thread.Sleep(10000) 放在循环末尾,10 秒后可以连接吗?如果您尝试使用命令行 telnet 连接到端口(即“telnet localhost 9999”),屏幕是否会显示已连接的空白?
您可以尝试添加哈希表来存储线程并在退出时删除它们,这增加了拥有线程列表并能够关闭连接并杀死它们的好处......
I agree with others that you might want to look at asynchronous methods instead of using separate threads for each connection, or at least BackgroundWorker... As for what is happening, did you try debugging making sure that you had one thread stuck on the AcceptTcpClient call? You could try specifying a high backlog in your Start() call. Could it be something with scope and maybe garbage collection of your thread because you don't maintain a reference for it? If you put a Thread.Sleep(10000) at the end of your loop, can you connect after 10 seconds? If you try using command line telnet to connect to the port (i.e. "telnet localhost 9999") does the screen blank showing that it connected?
You could try something like adding a hashtable to store your threads and remove them on exit which adds the benefit of having a list of them and being able to close the connections and kill them...