3

有一个使用 .NET Socket 和 TCP 协议的单线程服务器,以及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。整个服务器的来源

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

4

3 回答 3

1

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

于 2011-01-31T08:08:50.337 回答
0

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

最好的可能是:

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

这样,您就有了单独的不同队列来维护秩序。只有一个线程会处理一个队列/套接字。

于 2011-01-31T07:50:09.973 回答
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 认为它在发送所有数据之前就已经完成了,这很奇怪,但我相信他会。

于 2013-12-11T18:27:15.800 回答