我一直在测试运行udp服务器的各种语言/方法,以确定哪种语言/性能最高。到目前为止,我已经测试过.NET,NodeJs和Erlang。我发现这个代码片段丢失了超过我发送的50%的数据包,而node和.net的数量约为4%。方案是我尽快发送1000 20 byte messages
并将一个递增的数字打印到屏幕上。 Erlang只获得了约400个。你可以建议我做些什么来改善这个结果吗?
-module(udp).
-export([start/0]).
start() ->
spawn(fun() -> server(41235) end).
server(Port) ->
{ok, Socket} = gen_udp:open(Port, [binary, {active, false}]),
io:format("server opened socket:~p~n",[Socket]),
loop(Socket,0).
loop(Socket,N) ->
inet:setopts(Socket, [{active, once}]),
receive
{udp, Socket, Host, Port, Bin} ->
io:format("~p~n",[N]),
loop(Socket,N+1)
end.
如果我完全搞砸了这个erlang代码,我不会感到惊讶。我有一段非常困难的时间围绕着一些概念。
我的服务器感激地借鉴了:http://erlycoder.com/83/erlang-udp-socket-usage-example-with-gen
如果您有兴趣,请联系我的客户:
namespace LocalUdpClient
{
class Program
{
private static long _sentCount = 1;
private static CustomQueue _queue;
private static bool _continue = true;
static void Main(string[] args)
{
_queue = new CustomQueue();
_queue.ItemRemovedEventHandler += QueueOnItemRemovedEventHandler;
PopulateQueue();
var con = new System.Net.Sockets.UdpClient();
con.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 41235));
while (_continue)
{
byte[] bits = null;
if (_queue.TryDequeue(out bits))
{
con.SendAsync(bits, bits.Length);
Interlocked.Increment(ref _sentCount);
Console.Clear();
Console.Write(Interlocked.Read(ref _sentCount));
}
}
}
private static void QueueOnItemRemovedEventHandler(object sender, EventArgs eventArgs)
{
var queue = sender as CustomQueue;
if (queue.Count <= 0)
{
Task.Run(() => PopulateQueue()).Wait();
}
}
public static void PopulateQueue()
{
Console.ReadLine();
RandomNumberGenerator rand2 = new RNGCryptoServiceProvider();
Parallel.For(0, 1000, p =>
{
if (_queue.Count >= 1000) return;
byte[] bytes = new byte[20];
rand2.GetBytes(bytes);
_queue.Enqueue(bytes);
});
}
public class CustomQueue : ConcurrentQueue<byte[]>
{
public event EventHandler ItemRemovedEventHandler;
new public bool TryDequeue(out byte[] item)
{
var x = base.TryDequeue(out item);
if (ItemRemovedEventHandler != null)
{
ItemRemovedEventHandler(this,new EventArgs());
}
return x;
}
}
}
答案 0 :(得分:3)
与保证传送的TCP不同,UDP数据包可能只是被丢弃。通常这将是溢出的结果。在您拥有生产者/消费者关系的任何地方,您都需要关注当生产者消费者时会发生什么。使用TCP流量控制会对发送方施加压力,但是UDP不存在这样的背压。
当您在服务器端打开UDP套接字时,它将分配一定量的内存以从网络接收数据。如果您的客户端没有像从网络到达的数据那样快速地从套接字读取,您将遇到缓冲区溢出,新的UDP数据包将覆盖以前接收但尚未读取的UDP数据包。
您可以使用rcvbuf和sndbuf选项增加套接字的接收(和传输)缓冲区的大小。但是,您可能必须首先增加内核限制(例如sysctl -w net.core.rmem_max
)。
要查看是否丢失UDP数据包到内核缓冲区溢出,请使用netstat -su
检查UDP统计信息(查看“数据包接收错误”)。
答案 1 :(得分:0)
我认为有些数据包丢失了,因为在发送时没有人主动期待它们。 您可以通过以下方式修改Erlang代码来进一步减少收到的数据包数量:
io:format("~p~n",[N]),
receive after 10 -> ok end,
loop(Socket,N+1)
其中一个解决方案可能是使用{active, true}
选项,这将确保数据包将被定向到监听过程中。邮箱中。
作为旁注,在我的机器上,原始代码可以达到~99%的数据包接收速率,但在添加延迟后,Erlang部分只能接收几十个数据包。