Динамическое изменение порта TCPClient - PullRequest
0 голосов
/ 15 апреля 2011

Допустим, у вас есть следующий код.

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

Глядя на код, выясняется, что точка localend для клиента и точка remoteend для сервера, похоже, меняется на другой порт, но обратное значение в каждом случае остается тем же.

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 ]

3 голосов
/ 15 апреля 2011

Вы ошибаетесь в проблеме здесь;Создание нового потока для обработки TcpClient и последующий возврат к TcpListener.AcceptTcpClient() не не требует смены портов;Один сервер может получить несколько подключений к одному сокету.

В противном случае, как веб-серверы будут обрабатывать несколько пользователей одновременно?

Что-то еще не так с вашим кодом где-то.Ваш код «поток на соединение» не идеален (поток на соединение гораздо больше, чем нужно), но это быстрый и грязный способ, который прекрасно работает.

Как вы строитеслушатель?Что ты делаешь с клиентом?А что именно происходит с последующими соединениями?

1 голос
/ 15 апреля 2011

Я согласен с другими, что вы, возможно, захотите взглянуть на асинхронные методы вместо использования отдельных потоков для каждого соединения или, по крайней мере, 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);
    }
}
...