Socket.SendAsync不是在Mono / Linux上按顺序发送的

时间:2011-01-31 06:27:44

标签: c# linux sockets mono sendasync

有一个使用带有TCP协议的.NET Socket的单线程服务器,以及Socket.Pool()Socket.Select()Socket.Receive()

要发送,我用过:

public void SendPacket(int clientid, byte[] packet)
{
    clients[clientid].socket.Send(packet);
}

但是当向一个客户端发送大量数据(暂停整个主线程)时速度非常慢,所以我将其替换为:

public void SendPacket(int clientid, byte[] packet)
{
    using (SocketAsyncEventArgs e = new SocketAsyncEventArgs())
    {
        e.SetBuffer(packet, 0, packet.Length);
        clients[clientid].socket.SendAsync(e);
    }
}

它在带有.NET的Windows上运行正常(我不知道它是否完美),但在使用Mono的Linux上,数据包被丢弃或重新排序(我不知道)。使用Socket.Send()恢复为慢速版本适用于Linux。 Source for whole server

如何编写适用于Linux的非阻塞SendPacket()函数?

3 个答案:

答案 0 :(得分:1)

我会猜测它与您的using声明和SendAsync电话有关。也许e超出范围并且在SendAsync仍在处理缓冲区时被处置。但是这可能会引发异常。我真的只是在猜测。尝试删除using语句,看看会发生什么。

答案 1 :(得分:0)

我会说不滥用异步方法。你将找不到任何文件说明这个实际上被迫维持秩序。它将iem排队到一个可以分配给线程的scheuler,并且忽略了每个文档都没有维护oder,你可以自己打开实现细节。

最好的可能是:

  • 每个插槽都有一个队列。
  • 当您将dasta写入此队列并且没有工作线程时,启动工作项(ThreadPool)来处理该线程。

通过这种方式,您可以使用单独的不同队列来维护顺序。只有一个线程可以处理一个队列/套接字。

答案 2 :(得分:0)

我遇到了同样的问题; Linux和Windows对SendAsync的反应方式不同。有时linux会截断数据,但有一种解决方法。首先,您需要使用队列。每次使用SendAsync时都必须检查回调。 如果e.Offset + e.BytesTransferred< e.Buffer.Length,你只需要e.SetBuffer(e.Offset + e.BytesTransferred,e.Buffer.Length - e.BytesTransferred - e.Offset);并再次调用SendAsync。

我不知道为什么mono-linux相信它在发送所有数据之前已经完成了,这很奇怪,但我确信他确实如此。