动态更改TCPClient端口

时间:2011-04-15 05:02:18

标签: c# multithreading sockets tcp

假设你有以下代码。

 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?
        }
    }
  

查看代码   客户端的localendpoint和   服务器的remoteendpoint   似乎更改为不同的端口   然而,在每种情况下反过来仍然是   相同。

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}

2 个答案:

答案 0 :(得分:3)

这里的问题不正确;产生一个新线程来处理TcpClient然后循环回TcpListener.AcceptTcpClient() 而不是要求你更改端口;单个服务器可以在同一个套接字中获得多个连接。

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

您的代码在某处出现了其他问题。你的“每个连接的线程”代码并不理想(每个连接的线程远远超过需要),但它是一种快速而肮脏的方式,可以正常工作。

你是如何构建听众的?你在做什么与客户?后续连接究竟发生了什么?

答案 1 :(得分:1)

我同意其他人的观点,你可能想要查看异步方法而不是为每个连接使用单独的线程,或者至少使用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);
    }
}