2013-08-05 2 views
3

TCP를 통한 네트워크 스트림이 두 가지 방법 (클라이언트에서 서버로, 클라이언트에서 서버로)으로 Zlib 스트림입니다.NetworkStream을 통해 ZlibStream에서 읽음으로써 C# .Net에서 블로킹 문제가 발생합니다.

Zlib의 경우 최신 Ionic.Zlib.dll을 사용하고 있습니다.

송수신되는 첫 번째 몇 패킷의 경우 제대로 작동하지만 3 번째 패킷을 받으면 오작동합니다.

패킷이 반대쪽 끝까지 반복 될 때까지 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 회 전송 된 번만 받았다.

왜 차단합니까? 예상대로 차단하지 않고 계속 진행하려면 어떻게해야합니까?

Zlib에서 비워도 아무런 관련이 없습니까? (스트림은 모든 패킷 뒤에 플러시됩니다.)

+0

그것은 당신의 게시하면 도움을 줄 : 데이터가 psuedocode에서 ... 그것을 압축 해제 버퍼에있을 때 나는, 네트워크 스트림로부터 데이터를 읽어 그것을 버퍼, 그리고 다른 방법 불이있을 것이다 더 많은 코드. 여기에서 차단 읽기를 사용하고 있습니다. 코드를 리팩토링하여 비동기/대기 패턴과 비동기 읽기 (예 : ReadInt32Async)를 사용하도록하십시오. – Noseratio

+0

비동기 적으로 읽기가 내 문제를 해결하지 못합니다. – Codecat

+0

나는 양쪽 모두 읽고 쓰기를 의미 했으므로 아무 블록도 없다. – Noseratio

답변

2

Zlib 및 기타 압축 알고리즘은 데이터 블록으로 작동합니다. 소스 스트림에서 일부 데이터를 버퍼링 한 다음 압축하려고합니다.

버퍼 크기보다 작은 ZlibStream 데이터를 넣으면 실제로 ZlibStream에서 실제로 아무것도 나오지 않습니다. 버퍼가 가득 찰 때까지 데이터가 거기에 놓이게됩니다. 해당 데이터를 압축하려면 원본 스트림을 플러시하고 압축 된 스트림을 사용하는 것만으로는 충분하지 않습니다.

서비스가 ZlibStream을 닫으면 모든 readInt는 올바른 데이터를 받아야합니다.

서버에서 실시간으로 패킷을 받으려면 먼저 패킷을 완전히 압축 한 다음 네트워크 스트림을 통해 보내십시오.

+0

모든 패킷은 다음과 같이 스트림에서 압축되어 플러시됩니다. '78 5E <패킷의 바이트> 00 00 FF FF 00 00 00 FF FF <다른 패킷의 바이트> 00 00 FF FF 00 00 00 FF FF . 왜 정확히 충분하지 않습니까? – Codecat

+0

@alex는'ZlibStream'에서'Flush'를 호출하지 않으면 현재 압축 버퍼를 끝내고 압축 된 데이터를 원시 출력 스트림으로 보냅니 까? – Noseratio

+0

@Angelo, ZLibStream의'FlushMode'를'FlushType.Sync' 또는'FlushType.Full'로 설정합니까? – Noseratio

2

첫째, 당신은

는 "패킷이 다른 말을 반복 때까지 모든이 ZlibStream 블록에 작업을 읽습니다."라고

즉, 서버에 읽음이 있음을 의미합니다. 예 : 패턴은 그런 경우는 3 시간을 보내고 ReadInt32()있어 이후, 서버는 항상 차단합니다

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? 

... 같이해야한다. 다른 int 패킷이 서버에서 전송되는 것이 긍정적입니까?


두 번째로 ZlibStream을 네트워크 소켓에서 직접 읽지 않습니다.

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. 
관련 문제