.NET Async TcpListener / TcpClient Вопрос - PullRequest
3 голосов
/ 03 сентября 2010

Я немного растерялся относительно того, как правильно реализовать асинхронные методы для TcpListner и TcpClient int .NET. Я прочитал довольно много сообщений на слух, и я считаю, что у меня есть код, чтобы принимать новых клиентов на сервере, о котором позаботились. Вот код для приема новых соединений:

Public Sub Start()
    m_oListener = New TcpListener(m_oIpAddress, m_iPort)

    m_oListener.Start()
    m_oListener.BeginAcceptTcpClient(New AsyncCallback(AddressOf OnAcceptClient), m_oListener)
End Sub

Public Sub OnAcceptClient(ByVal ar As IAsyncResult)
    Dim listener As TcpListener = CType(ar.AsyncState, TcpListener)
    Dim client As TcpClient = listener.EndAcceptTcpClient(ar)

    If listener.Server.IsBound Then
        ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf OnHandleClient), client)
        listener.BeginAcceptTcpClient(New AsyncCallback(AddressOf OnAcceptClient), listener)
    End If
End Sub

В чем я не уверен, так это в том, что делать с клиентом после установления соединения. Из того, что я видел, обычно люди создают новый поток для каждого подключенного клиента, чтобы предотвратить блокировку приложения при чтении операций ввода-вывода.

Мое приложение будет иметь до 100 подключенных клиентов в любой момент времени. Если я раскрою новую ветку для каждого клиента, у меня будет около 100 нитей. Это верно? Я думаю, что я что-то упускаю из-за асинхронных методов в .NET Framework.

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

Спасибо за любую помощь заранее.

Ответы [ 2 ]

2 голосов
/ 03 сентября 2010

После того, как вы извлекли ссылку на TcpClient в вашем обратном вызове OnAcceptClient, вы захотите получить NetworkStream через GetStream, а затем немедленно вызвать BeginRead (или BeginWrite), чтобы запустить асинхронныйоперация.Следующие BeginRead будут соединены в цепочку после того, как вы позвоните по номеру EndRead, как вы делаете с TcpListener.

1 голос
/ 03 сентября 2010

Вы можете иметь 100 потоков, каждый из которых обрабатывает одного клиента, и это будет хорошо.У вас также может быть один поток, который проходит по всем вашим клиентам и асинхронно обрабатывает ввод-вывод.

Делая эту асинхронную работу, вам не нужно беспокоиться о том, что ваш отдельный поток занимает слишком много времени для обработки каждого соединения.

Если вы собираетесь масштабировать намного выше, чем говоритепотребуется обработка нескольких клиентов в потоке.

Псевдокод:

foreach TcpClient
    if DataAvailable
        BeginRead()
...