Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets Erlang Udp服务器丢弃大量数据包_Sockets_Erlang - Fatal编程技术网

Sockets Erlang Udp服务器丢弃大量数据包

Sockets Erlang Udp服务器丢弃大量数据包,sockets,erlang,Sockets,Erlang,我一直在测试运行udp服务器的各种语言/方法,看看哪种语言/方法性能最好。到目前为止,我已经测试了.NET、NodeJs和Erlang。我发现这个代码剪切掉了我发送的超过50%的数据包有问题,而node和.net的数据包下降了约4%。这个场景是我尽可能快地发送1000条20字节的消息,并在屏幕上打印一个递增的数字。Erlang只得到了约400个。你能建议我能做些什么来改善这个结果吗 -module(udp). -export([start/0]). start() -> spaw

我一直在测试运行udp服务器的各种语言/方法,看看哪种语言/方法性能最好。到目前为止,我已经测试了.NET、NodeJs和Erlang。我发现这个代码剪切掉了我发送的超过50%的数据包有问题,而node和.net的数据包下降了约4%。这个场景是我尽可能快地发送
1000条20字节的消息
,并在屏幕上打印一个递增的数字。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代码,我也不会感到惊讶。我真的很难理解其中的一些概念

我的服务器非常感激地借用了:

这是我的客户,如果您感兴趣:

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;

        }


    }
}
名称空间LocalUdpClient
{
班级计划
{
私有静态长计数=1;
私有静态CustomQueue\u队列;
私有静态bool _continue=true;
静态void Main(字符串[]参数)
{
_queue=新CustomQueue();
_queue.ItemRemovedEventHandler+=QueueOnItemRemovedEventHandler;
PopulateQueue();
var con=new System.Net.Sockets.UdpClient();
con.Connect(新的IPEndPoint(IPAddress.Parse(“127.0.0.1”),41235));
while(_continue)
{
字节[]位=空;
if(_queue.TryDequeue(out位))
{
con.SendAsync(位、位、长度);
联锁增量(参考计数);
Console.Clear();
控制台写入(联锁读取(参考sentCount));
}
}
}
私有静态void QueueOnItemRemovedEventHandler(对象发送方,EventArgs EventArgs)
{
var queue=发送方作为CustomQueue;
if(queue.Count PopulateQueue()).Wait();
}
}
公共静态void PopulateQueue()
{
Console.ReadLine();
RandomNumberGenerator rand2=新的RNGCryptoServiceProvider();
对于(0,1000,p=>
{
如果(_queue.Count>=1000)返回;
字节[]字节=新字节[20];
rand2.GetBytes(字节);
_queue.Enqueue(字节);
});
}
公共类CustomQueue:ConcurrentQueue
{
公共事件事件处理程序ItemRemovedEventHandler;
新的公共bool TryDequeue(输出字节[]项)
{
var x=base.TryDequeue(out项);
if(ItemRemovedEventHandler!=null)
{
ItemRemovedEventHandler(这是新的EventArgs());
}
返回x;
}
}
}

我认为有些数据包丢失了,因为在发送时,没有人积极地期待它们。 通过以下方式修改Erlang代码,可以进一步减少收到的数据包数:

        io:format("~p~n",[N]),
        receive after 10 -> ok end,
        loop(Socket,N+1)
其中一个解决方案可能是使用
{active,true}
选项,该选项将确保数据包被定向到侦听进程的邮箱


顺便说一句,在我的机器上,原始代码可以达到约99%的数据包接收率,但在添加延迟后,Erlang部分只能接收几十个数据包。

与TCP不同,TCP保证传输,UDP数据包可以简单地丢弃。通常这是溢出的结果。在任何有生产者/消费者关系的地方,你都需要关注当生产者超过消费者时会发生什么。使用TCP流控制会对发送方施加背压,但是使用UDP时不存在此类背压

当您在服务器端打开UDP套接字时,它将分配一定数量的内存以从网络接收数据。如果您的客户端在数据从网络到达时没有以最快的速度从套接字读取数据,您将遇到缓冲区溢出,新的UDP数据包将覆盖以前接收到但尚未读取的UDP数据包

您可以使用rcvbuf和sndbuf选项增加套接字的接收(和发送)缓冲区的大小。但是,您可能必须首先增加内核限制(例如,
sysctl-w net.core.rmem_max


要查看是否由于内核缓冲区溢出而丢失UDP数据包,请使用
netstat-su
(查看“数据包接收错误”)检查UDP统计信息。

Active true仅将成功率略微提高了约15%。我应该补充一点,我的代码snip将环回显示为服务器,但实际上服务器是一个ec2 ubuntu 14.04实例,我的客户端在我的家庭网络上。您是否也在AWS上测试了您的.NET和Node.js服务器?是的,Node使用相同的环境,而.NET使用不同的windows实例。我本来打算在linux上尝试使用.NET Core,但System.Sockets命名空间尚未完成。我只是在同一台linux主机上使用mono重新编译了.NET服务器,成功率为96.3%。@Wjdavis5我有你的代码,这行io:format(“~p~n”,[n])似乎永远不会执行。这在erlang shell中没有输出。你能告诉我原因吗?-我有你的代码,这行
io:format(~p~n“,[n]),
似乎永远不会执行。这在erlang shell中没有输出。你能告诉我是什么原因吗?你寄了一包吗?该行仅在收到数据包时打印。谢谢,我了解udp的工作原理,我正在寻求有关erlang代码剪切的帮助。erlang代码丢失了70%的数据包,而.net/mono/nodjs/python版本只丢失了约5-10%。了解数据包丢失的位置很重要。您的Erlang服务器进程读取套接字的速度不够快,这是一个问题吗?我已经解释了如何诊断它以及如何优化代码。好的,我很感激。在我重读你的答案后,我明白你现在在说什么了。我已将net.core.rmem_max设置为8MB,并将套接字recvbuf设置为4194304,现在是am