c# - 如何确定异步套接字服务器中的流结束

标签 c# sockets asynchronous stream

我正在尝试用 C# 编写一个异步套接字。我阅读了很多 msdn 文章并找到了这两个示例:server , client .

我了解示例代码并使用它来实现我自己的异步套接字。在示例中,服务器检查 <EOF>确定流的结尾并发送响应。我想知道流结束时不检查特殊文字。我的想法是检查 (bytesRead > 0)并调用handler.BeginReceive()递归地。 请参阅以下内容:

Original

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));

    // Check for end-of-file tag. If it is not there, read 
    // more data.
    content = state.sb.ToString();
    if (content.IndexOf("<EOF>") > -1) {
        // All the data has been read from the 
        // client. Display it on the console.
        Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
            content.Length, content );
        // Echo the data back to the client.
        Send(handler, content);
    } else {
        // Not all data received. Get more.
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
        new AsyncCallback(ReadCallback), state);
    }
}

My idea

if (received > 0)
{
    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, received));
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
else
    Send(handler, state.sb.ToString());

如果我用我的部分替换原始部分,程序将停止运行。 我猜客户端执行 EndSend()SendCallback()并在 receiveDone.WaitOne() 之后阻塞线程在StartClient() .我怎么能通过这个?是否需要使用确定流结束的 token ?

还有其他好的示例代码吗?我刚找到那两个。

(证据。服务器应该接收在线客户端并将它们放入循环缓冲区,他应该使用多线程读取和处理记录。)

编辑

如果我使用以下内容:

if (receive > 0)
    state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, receive));
if (receive == StateObject.BufferSize)
    state.listener.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
else
    Send(state.listener, state.sb.ToString());

我猜一切都很好。可以吗?还是想念什么?

如果我将这两个 if 结合起来,它就不会再起作用了。为什么?

if(receive > 0 || receive == StateObject.BufferSize) -> if(receive > 0) // Not working.

最佳答案

您的代码版本的问题是您启动了 BeginReceive总是,但在一种情况下,即当有 0 时收到的字节数。事实上,大多数情况下,当您收到的数据量不为零且小于缓冲区大小时(有时恰好是缓冲区大小时),传输就会结束。收货0字节永远不会发生,因为这意味着没有传输而不是传输结束。这是假设发送方通过关闭连接来结束传输。

有多种方式来指示传输结束:

  • 发送者关闭连接
  • 发送特殊序列(如 EOF)
  • 接收者得到了他所期望的(因为它首先得到了标题)

第一种方法的问题是关闭(和重新打开)连接通常很昂贵。 header 的问题是,如果您错过了一个 header (由于某些网络问题),您就迷路了——您不知道下一个 header 何时到来,因为您不知道当前数据包何时结束(丢失 header )。出现问题时最简单的恢复以某种形式提供 EOF。它不一定是字面上的 <EOF>字符串,它可以是(很可能)永远不会出现在您的正常数据流中的任何东西。

话虽如此,没有什么可以阻止您将 header 与 EOF 结合使用或包含记录开始的特殊序列标记的 header 。

关于c# - 如何确定异步套接字服务器中的流结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15791769/

相关文章:

java - 通过对象序列化流发送具有不同字段的相同对象

python - 尝试从网页读取数据时的回溯

asynchronous - 如何在生成器中使用 await?

java - 为什么异常完成前调用get()会等待异常执行?

javascript - 动态加载 javascript,检查所有 javascript 何时加载

c# - Entity Framework 扩展方法 ICollection/IQueryable

c# - 多个 View 的相同命令

java - 非阻塞套接字

c# - 访问 process.MainModule.FileName 时出现拒绝访问异常

c# - 使用泛型调用重载方法