2013-08-05 3 views
3

У меня есть сетевой поток через TCP, который является потоком Zlib в обоих направлениях (клиент к серверу и сервер к клиенту).Чтение из ZlibStream поверх NetworkStream, дающее проблемы с блокировкой в ​​C# .Net

Для Zlib, я использую последние Ionic.Zlib.dll.

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

Каждая операция чтения на блоке ZlibStream блокируется до тех пор, пока пакет не будет повторен другим концом.

Например:

// Where reader is a BinaryReader on the ZlibStream on the NetworkStream 
int a = reader.ReadInt32(); // blocks until initial packet that is 12 bytes is received 
int b = reader.ReadInt32(); // blocks until the packet is repeated 
int c = reader.ReadInt32(); // blocks until the packet is repeated again 

После этого кода, пакет фактически был отправлен в 3 раза и получил только один раз.

Почему это блокируется? Как я могу заставить его не блокировать и продолжать, как ожидалось?

Может ли промывка в Злибе иметь какое-либо отношение к ней? (Поток очищается после каждого пакета.)

+0

Было бы полезно, если ваш отправил больше кода. Вы используете блокирующие чтения здесь, подумайте о том, как реорганизовать ваш код, чтобы использовать шаблоны async/await и асинхронные чтения (т. Е. ReadInt32Async). – Noseratio

+0

Чтение асинхронно не решит мою проблему. – Codecat

+0

Я имел в виду и чтение, и запись - оба конца, поэтому блоков нет. – Noseratio

ответ

2

Zlib, а также другие алгоритмы сжатия, работают с блоками данных. Он буферизует некоторые данные из исходного потока, а затем пытается сжать его.

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

Все ваши readInts должны получать правильные данные, если служба закрывает ZlibStream.

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

+0

Все пакеты сжимаются и продуваются в потоке, как показано здесь: '78 5E <байты пакета> 00 00 FF FF 00 00 00 FF FF <байты другого пакета> 00 00 FF FF 00 00 00 FF FF <байты другой пакет> и т. д. 'Почему именно этого недостаточно? – Codecat

+0

@alex, не вызывая 'Flush' на' ZlibStream', заканчивает текущий буфер сжатия и отправляет сжатые данные в исходный поток вывода? – Noseratio

+0

@Angelo, вы устанавливаете 'FlushMode' на свой ZLibStream на' FlushType.Sync' или 'FlushType.Full'? – Noseratio

2

Во-первых, вы говорите

«Каждый операции чтения на блоках ZlibStream, пока пакет не повторяется на другом конце.»

Это означает, что на вашем сервере прочитано ... например. образец должен быть как ...

Client: Connects to server, asks for data 
Server: Sends packet 
Client: Reads packet 
Client: Sends same packet back 
Server: Reads Packet 
Server: Sends new packet? 

Если это так, то сервер будет всегда блокировать, так как вы ReadInt32() ING 3 раза. Вы уверены, что другие пакеты int отправлены вашим сервером?


Во-вторых, я бы не использовал ZlibStream для чтения непосредственно из сетевого сокета. Я прочитал в исходных данных из сетевого потока, буфера, и есть другой метод огонь, когда данные были в буфере, что распакованного его ... В psuedocode:

byte[] compressedDataBuffer 
bool canReadFromBuffer = false; 
ASYNC: 
    while(true): 
     get current network stream, see if there's data 
     if it has data: 
      add networkStream's current data to compressedDataBuffer 
      lock: 
       if compressedDataBuffer has new data/has enough data 
        canReadFromBuffer = true 
       else 
        canReadFromBuffer = false 
     else: 
      sleep(0); //yield cycles 
SYNC: 
    while(true): 
     if canReadFromBuffer: 
      create a memory stream of compressedDataBuffer 
      create a zlibstream around that memory stream 
      perform operations on the zlibstream that are required.