动态更改 TCPClient 端口

发布于 2024-11-01 02:57:07 字数 1536 浏览 0 评论 0原文

假设您有以下代码。

 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

二智少女 2024-11-08 02:57:07

你对这里的问题的理解是错误的;生成一个新线程来处理 TcpClient,然后循环回 TcpListener.AcceptTcpClient() 并不需要您更改端口;单个服务器可以将多个连接连接到同一套接字。

否则,网络服务器如何同时处理多个用户?

您的代码在某处出现了其他问题。您的“每个连接一个线程”代码并不理想(每个连接一个线程远远超出了需要),但它是一种快速而肮脏的方式,效果很好。

您如何构建监听器?你在和客户做什么?后续连接到底发生了什么?

You are incorrect about the problem here; Spawning a new thread to handle the TcpClient and then looping back to TcpListener.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?

2024-11-08 02:57:07

我同意其他人的观点,您可能希望查看异步方法,而不是为每个连接使用单独的线程,或者至少是BackgroundWorker...至于发生的情况,您是否尝试调试以确保有一个线程卡在 AcceptTcpClient 上称呼?您可以尝试在 Start() 调用中指定高积压。它是否可能是具有范围的东西,并且可能是线程的垃圾收集,因为您没有维护它的引用?如果将 Thread.Sleep(10000) 放在循环末尾,10 秒后可以连接吗?如果您尝试使用命令行 telnet 连接到端口(即“telnet localhost 9999”),屏幕是否会显示已连接的空白?

您可以尝试添加哈希表来存储线程并在退出时删除它们,这增加了拥有线程列表并能够关闭连接并杀死它们的好处......

Dictionary<TcpClient, Thread> _threads = new Dictionary<TcpClient, Thread>();
object _lockObject = new object();

void AddThread(TcpClient client, Thread thread)
{
    lock (_lockObject)
    {
        _threads.Add(client, thread);
    }
}

void RemoveThread(TcpClient client)
{
    lock (_lockObject)
    {
        _threads.Remove(client);
    }

}

void YourMainMethod()
{
    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));
         AddThread(client, clientThread);
         clientThread.Start(client);
    }
}


private void HandleClientCommunication(object client)
{
    try
    {
        using (TcpClient tcpClient = (TcpClient) client)
        {
            //Do my work
        }
    } catch (Exception)
    {
         // so program doesn't crash
    }
    finally
    {
        RemoveThread((TcpClient)client);
    }
}

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...

Dictionary<TcpClient, Thread> _threads = new Dictionary<TcpClient, Thread>();
object _lockObject = new object();

void AddThread(TcpClient client, Thread thread)
{
    lock (_lockObject)
    {
        _threads.Add(client, thread);
    }
}

void RemoveThread(TcpClient client)
{
    lock (_lockObject)
    {
        _threads.Remove(client);
    }

}

void YourMainMethod()
{
    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));
         AddThread(client, clientThread);
         clientThread.Start(client);
    }
}


private void HandleClientCommunication(object client)
{
    try
    {
        using (TcpClient tcpClient = (TcpClient) client)
        {
            //Do my work
        }
    } catch (Exception)
    {
         // so program doesn't crash
    }
    finally
    {
        RemoveThread((TcpClient)client);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文