首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用.NET缓冲和处理实时组播数据

用.NET缓冲和处理实时组播数据
EN

Stack Overflow用户
提问于 2013-01-08 23:55:48
回答 1查看 1.3K关注 0票数 0

我正在尝试解析通过多播接收的MPEG2-TS数据。问题是,接收方法有时会跳过数据包-我相信这在很大程度上取决于连续的接收()方法之间所做的额外处理。根据我所做的研究,如果CPU不在接收()方法上,数据包将会丢失,所以缓冲将是不立即处理的最快选择,并让这项工作由另一个线程完成……我说的对吗?。

我目前正在使用一个队列来保存接收到的数据报,以便稍后通过使用dequeue方法从另一个线程进行处理。我还切换到使用在新线程上初始化的阻塞多播接收器,而不是异步接收器,以确保没有延迟从一个线程委托到另一个线程,例如,当使用OnReceiveFrom()方法时。

组播接收器的代码如下:

代码语言:javascript
复制
class Multicast
{
    /// <summary>
    /// The possible Operating Modes allowed for this Multicast Class File
    /// </summary>
    public enum OperationMode
    {
        Client,
        Server
    };

    private IPAddress ipAddress;
    private int portNumber;
    private int interfaceIndex;
    private Socket socket;
    private EndPoint sourceOrDestination;
    private byte[] Data;
    private OperationMode operationMode;

    public Queue<byte[]> q = new Queue<byte[]>();

    public Multicast(string ipAddress, int portNumber, int interfaceIndex, OperationMode operationMode)
    {
        if (!IPAddress.TryParse(ipAddress, out this.ipAddress))
        {
            throw new Exception("Incorrect Argument Data. Unable to parse IP Address!");
        }
        this.portNumber = portNumber;
        this.interfaceIndex = interfaceIndex;
        this.operationMode = operationMode;
    }

    public void Start()
    {
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, portNumber); // Local IP and Port (if more than one NIC interface is available, this command must be altered!

        //socket.SetSocketOption(SocketOptionLevel.Udp,SocketOptionName.Broadcast,true);
        socket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.NoDelay, 1);
        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); // Allow for loopback testing 
        socket.Bind(localEndPoint); // Extremly important to bind the Socket before joining multicast groups 
        socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, Properties.Settings.Default.Network_MulticastTTL); // Set TTL (e.g.: 1 for one router hop)
        try
        {
            socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ipAddress, interfaceIndex)); // Join Multicast
        }
        catch (Exception) { }
        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, Properties.Settings.Default.Network_FramePayloadSize);
        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, Properties.Settings.Default.Network_FramePayloadSize);
        //socket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.DontFragment, 1);
        socket.DontFragment = true;



        while (true)
        {
            Data = new byte[socket.ReceiveBufferSize];
            socket.Receive(Data);

            q.Enqueue(Data);
        }
    }

    /// <summary>
    /// This function is used to stop the socket from sending/receiving further data. The socket is therefore closed.
    /// </summary>
    public void Stop()
    {
        socket.Close();
    }
}

即使从字面上将接收到的所有数据报转储到.ts文件中,人们也可能会注意到在VLC中播放时的像素和音频跳过。实际上,由于wireshark按顺序显示所有数据包,因此NIC卡可以成功接收数据包,并且可以在VLC中播放流,而不会出现问题(直接打开流)。

你有什么建议来改善结果呢?

EN

回答 1

Stack Overflow用户

发布于 2013-01-09 02:48:04

正如我所想的那样,您将套接字接收缓冲区限制为大约一个数据报。为ReceiveBuffer提供的SetSocketOption的值应该更大,这样内核就有足够的空间为您缓冲几个输入数据报,同时您的应用程序不会立即从套接字读取(例如处理您当前的输入)。将当前接收缓冲区大小值乘以100。

那么你在回复中所说的关于字节为零的评论就没有多大意义。看看你的代码-你没有考虑到Receive()的返回值(即实际收到的字节数),而是假设你每次都会得到ReceiveBufferSize字节。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14218948

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档