C#套接字接收:接收数据直到缓冲区完全陷入困境

时间:2016-04-27 04:25:47

标签: c# sockets buffer hang receiver

这是我的代码我遇到了问题:

// read the file in chunks of 5KB
var buffer = new byte[1024*5];
int bytesRead = 0;
do
{
    bytesRead = host.Receive(buffer, buffer.Length, 0);
    output.Write(buffer, 0, bytesRead);
}
while (bytesRead == buffer.Length);

所以这就是我的问题:只要缓冲区已满,我就想读取数据。但是,即使有更多数据,也不保证在发送时填充缓冲区。这会导致Receive过早退出。如果我将while条件更改为bytesRead > 0,那么它将到达数据的末尾并接收块,直到有更多数据可用(它不会成功)。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

我认为您需要考虑协议如何工作并制定更强大的解决方案。您可以使用阻止功能,然后您可以等到没有更多数据要读取,然后执行其他操作并在您知道有更多数据需要阅读时再次阅读。

或者你添加了线程并且只有一个单独的线程可以读取,然后如果它阻塞它并不重要,因为它将在一个单独的线程上。

另一种可能更简单的解决方案是使用异步读取。

您可以在此处详细了解:https://msdn.microsoft.com/en-us/library/bbx2eya8(v=vs.110).aspx

上述网站的一个简单示例是从read:

开始
private static void Receive(Socket client) {
    try {
        // Create the state object.
        StateObject state = new StateObject();
        state.workSocket = client;

        // Begin receiving the data from the remote device.
        client.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReceiveCallback), state);
    } catch (Exception e) {
        Console.WriteLine(e.ToString());
    }
}

然后,当有数据需要处理时,您将收到ReceiveCallback的回调:

private static void ReceiveCallback( IAsyncResult ar ) {
    try {
        // Retrieve the state object and the client socket 
        // from the asynchronous state object.
        StateObject state = (StateObject) ar.AsyncState;
        Socket client = state.workSocket;
        // Read data from the remote device.
        int bytesRead = client.EndReceive(ar);
        if (bytesRead > 0) {
            // There might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
                //  Get the rest of the data.
            client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
                new AsyncCallback(ReceiveCallback), state);
        } else {
            // All the data has arrived; put it in response.
            if (state.sb.Length > 1) {
                response = state.sb.ToString();
            }
            // Signal that all bytes have been received.
            receiveDone.Set();
        }
    } catch (Exception e) {
        Console.WriteLine(e.ToString());
    }
}

我希望如果不能,我们需要了解更多关于您使用的协议的信息,如果有某些原因需要阻止读取,那么我们可以提供更具体的信息和帮助。