VB.NET Асинхронные сокеты пакеты теряются - PullRequest
0 голосов
/ 16 октября 2011

Я создал TCP-сервер, который обменивается данными с несколькими клиентами одновременно, но я не могу сделать их стабильными. Когда один из клиентов отправляет 100 пакетов на сервер, сервер получает только несколько из них.

Вот код клиента в PasteBin . Он показывает, как клиент подключается к серверу, а затем отправляет на сервер 100 сообщений в цикле For.

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

1 Ответ

1 голос
/ 16 октября 2011

Я также ответил на ваш вопрос по поводу reddit, но решил, что отвечу здесь, если кто-то еще ищет подобные вещи.

У вас две проблемы с обработкой вашего серверачитает.Прежде всего, конструктор вашего клиентского объекта:

Public Sub New(ByVal client As TcpClient)
    'New client connects
    Me.client = client
    client.GetStream().BeginRead(New Byte() {0}, 0, 0, AddressOf Read, Nothing)
End Sub

BeginRead ожидает, что вы будете собирать данные таким образом, чтобы их можно было передать в метод обратного вызова;«Читать» в этом случае.Как правило, это делается путем создания нового объекта для хранения «State» этой асинхронной операции и передачи его в качестве последнего параметра в BeginRead.Ваш вызов метода здесь создает новый байтовый массив, но не содержит ссылку на него для передачи в качестве последнего аргумента метода.Это означает, что данные, которые будут прочитаны этим вызовом, просто исчезнут после чтения, поскольку они никогда не будут переданы в метод для его хранения.

Во-вторых, ваша операция чтения:

Public Sub Read(ByVal ar As IAsyncResult)
    Dim reader As New StreamReader(client.GetStream())
    clientPacket &= reader.ReadLine()
    client.GetStream().BeginRead(New Byte() {0}, 0, 0, AddressOf Read, Nothing)
End Sub

Поскольку вы не передаете данные, которые были прочитаны в асинхронном вызове, вы создаете новый StreamReader для получения дополнительных данных от клиента.Это не асинхронный вызов метода.Ваш вызов reader.ReadLine () будет блокироваться до тех пор, пока не встретится новая строка, после чего данные будут добавлены в clientPacket.Затем вы снова вызываете BeginRead с той же проблемой, что и выше, что означает, что вы потеряете больше данных.

Кроме того, вы никогда не очищаете свои объекты AsyncResult, вызывая EndRead () в потоке, чтов конечном итоге это приводит к нехватке ресурсов, когда в CLR заканчиваются рабочие потоки для ваших асинхронных операций.

Вот пример того, как я реализовал бы такую ​​задачу.Это в C #, так как это то, что мне больше всего нравится, так что извините за это.;)

Код клиента

Код сервера

Надеюсь, это поможет!

...