套接字C#上的多线程

时间:2014-05-01 14:49:32

标签: c# multithreading sockets

我正在尝试使用线程同时从多个IP捕获网络数据包,但是我得到了这个异常“由于系统缺少足够的缓冲区空间或因为队列缺乏,因此无法执行套接字上的操作全”。我是线程和套接字的新手。例外来自“ mainSocket.BeginReceive(_data,0,_data.Length,SocketFlags.None,OnReceive,null);

         IPHostEntry HosyEntry = Dns.GetHostEntry((Dns.GetHostName()));
         if (HosyEntry.AddressList.Length > 0)
         {
             foreach (IPAddress ip in HosyEntry.AddressList)
             {
                 if (ip.IsIPv6LinkLocal == false)
                 {
                     SetIp ipAdd = new SetIp();
                     ipAdd.SetIpAdd(ip);    
                 }
             }
         }

    class SetIp
{
    private Socket mainSocket;                         
    private byte[] _data = new byte[4096];

    public void SetIpAdd(IPAddress address)
    {

        mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
        mainSocket.Bind(new IPEndPoint(address, 0));

         Thread MyThread = new Thread(new ThreadStart(() =>{
             while (true)
             {

                 mainSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
                 byte[] byTrue = new byte[] { 1, 0, 0, 0 };
                 byte[] byOut = new byte[] { 1, 0, 0, 0 };

                 mainSocket.IOControl(IOControlCode.ReceiveAll, byTrue, byOut);


                 mainSocket.BeginReceive(_data, 0, _data.Length, SocketFlags.None, OnReceive, null);


             } }));

         MyThread.Start();
     }

    private void OnReceive(IAsyncResult ar)
    {

        var received = mainSocket.EndReceive(ar);
        Parse(_data, received);
        mainSocket.BeginReceive(_data, 0, _data.Length, SocketFlags.None, OnReceive, null);

    }

    private void Parse(byte[] data, int size)
    {
        IPHeader ipHeader = new IPHeader(data, size);
        Console.WriteLine( ipHeader.SourceIP.ToString());
    }

2 个答案:

答案 0 :(得分:1)

您在热循环中无限次地呼叫BeginReceive。这导致无限多的IO排队。

您可能希望使用同步IO,因为它更易于使用。或者,只发出最后一个完成的下一个读物。

答案 1 :(得分:1)

使用Receive方法代替BeginReceive方法。

    mainSocket.Receive(byteData, 0, byteData.Length, SocketFlags.None);

                ParseData(byteData, byteData.Length);