3

我有一个基于 TCP 的网络流,它是Zlib双向流(客户端到服务器和服务器到客户端)。

因为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 次,并且只接收了一次。

为什么会堵在那里?我怎样才能让它不阻塞并按预期继续?

在 Zlib 中刷新可能与它有关吗?(每个数据包后都会刷新流。)

4

2 回答 2

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 直接从网络套接字读取。我会从网络流中读取原始数据,对其进行缓冲,并在数据位于解压缩它的缓冲区中时触发另一种方法......在伪代码中:

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.
于 2013-08-13T15:58:01.933 回答
2

Zlib 以及其他压缩算法对数据块进行操作。它缓冲来自源流的一些数据,然后尝试对其进行压缩。

如果您放入小于缓冲区大小的 ZlibStream 数据,则实际上不会立即从 ZlibStream 中输出任何内容。您的数据将保留在那里,直到缓冲区填满。要压缩该数据,刷新您的原始流,甚至可能是压缩流,是不够的。

如果 serve 关闭了 ZlibStream,你所有的 readInts 都应该收到正确的数据。

如果您想实时接收来自服务器的数据包,请先尝试将数据包完全压缩,然后通过网络流发送。

于 2013-08-08T07:24:09.987 回答