当前位置: 代码迷 >> C# >> 监控端口的流量的原理?怎么监控某端口的流量
  详细解决方案

监控端口的流量的原理?怎么监控某端口的流量

热度:75   发布时间:2016-05-05 03:11:53.0
监控端口的流量的原理?如何监控某端口的流量?
比如QQ通过端口1234正在接受文件,那么如何用第三方软件同时去监控这个1234端口的数据流量情况呢?

楼主现在在调研实现方法。。。
------解决思路----------------------
api hook或者写底层驱动
------解决思路----------------------
引用:
api hook或者写底层驱动

c#可以写底层驱动?
------解决思路----------------------
C# 在windows 上什么都可以干
------解决思路----------------------
hook  winapi 就可以实现监控.
------解决思路----------------------
原始套接字,参考fastCSharp的demo.rawSocketListener
using System;
using fastCSharp;

namespace fastCSharp.demo.rawSocketListener
{
    class Program
    {
        /// <summary>
        /// 原始套接字监听
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Console.WriteLine("Press ip and enter ");
            string ip = Console.ReadLine();
            if (ip.length() == 0) Console.WriteLine(ip = "192.168.1.100");
            try
            {
                using (fastCSharp.net.rawSocketListener rawSocket = new fastCSharp.net.rawSocketListener(getPacket, System.Net.IPAddress.Parse(ip)))
                {
                    if (rawSocket.IsDisposed)
                    {
                        if (rawSocket.LastException != null) Console.WriteLine(rawSocket.LastException.ToString());
                        Console.WriteLine("套接字监听失败,可能需要管理员权限运行。");
                    }
                    else
                    {
                        Console.WriteLine("Press quit to exit.");
                        while (Console.ReadLine() != "quit") ;
                        return;
                    }
                }
            }
            catch (Exception error)
            {
                Console.WriteLine(error.ToString());
            }
            Console.ReadKey();
        }
        /// <summary>
        /// 数据包处理
        /// </summary>
        /// <param name="data">数据包</param>
        private static void getPacket(subArray<byte> data)
        {
            fastCSharp.net.packet.ip ip4 = new fastCSharp.net.packet.ip(data);
            if (ip4.IsPacket)
            {
                switch (ip4.Protocol)
                {
                    case fastCSharp.net.packet.ip.protocol.Icmp:
                        fastCSharp.net.packet.icmp icmp = new fastCSharp.net.packet.icmp(ip4.Packet);
                        if (icmp.IsPacket)
                        {
                            Console.WriteLine(ip4.Source.toHex8() + " -> " + ip4.Destination.toHex8() + " " + ip4.Protocol.ToString() + " " + icmp.Type.ToString() + " " + icmp.Code.ToString());
                        }
                        else Console.WriteLine("Unknown");
                        break;
                    case fastCSharp.net.packet.ip.protocol.Igmp:
                        fastCSharp.net.packet.igmp igmp = new fastCSharp.net.packet.igmp(ip4.Packet);
                        if (igmp.IsPacket)
                        {
                            Console.WriteLine(ip4.Source.toHex8() + " -> " + ip4.Destination.toHex8() + " " + ip4.Protocol.ToString());
                        }
                        else Console.WriteLine("Unknown");
                        break;
                    case fastCSharp.net.packet.ip.protocol.Tcp:
                        fastCSharp.net.packet.tcp tcp = new fastCSharp.net.packet.tcp(ip4.Packet);
                        if (tcp.IsPacket)
                        {
                            Console.WriteLine(ip4.Source.toHex8() + ":" + ((ushort)tcp.SourcePort).toHex() + " -> " + ip4.Destination.toHex8() + ":" + ((ushort)tcp.DestinationPort).toHex() + " " + ip4.Protocol.ToString());
                        }
                        else Console.WriteLine("Unknown");
                        break;
                    case fastCSharp.net.packet.ip.protocol.Udp:
                        fastCSharp.net.packet.udp udp = new fastCSharp.net.packet.udp(ip4.Packet);
                        if (udp.IsPacket)
                        {
                            Console.WriteLine(ip4.Source.toHex8() + ":" + ((ushort)udp.SourcePort).toHex() + " -> " + ip4.Destination.toHex8() + ":" + ((ushort)udp.DestinationPort).toHex() + " " + ip4.Protocol.ToString());
                        }
                        else Console.WriteLine("Unknown");
                        break;
                    default:
                        Console.WriteLine(ip4.Source.toHex8() + " -> " + ip4.Destination.toHex8() + " " + ip4.Protocol.ToString());
                        break;
                }
            }
            else Console.WriteLine("Unknown");
            byte[] buffer = data.Array;
            fastCSharp.net.rawSocketListener.Free(ref buffer);
        }
    }
}

------解决思路----------------------
这个不需要hook api(而且C#托管dll去做底层的钩子不太现实)
但是.Net socket提供了IO控制,你需要地作IP层监听
this.listener.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
this.listener.Bind(ipPoint);
 var output = new byte[4];
 this.listener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, output);


public partial class FrmSynPortData
    {
        private Socket listener;
        //private IList<ArraySegment<byte>> buffer = new List<ArraySegment<byte>>();
        private byte[] buffer = new byte[65536];     //缓冲
        private int transfered = 0; //传输的字节数       

        public FrmSynPortData()
        {
            InitializeComponent();
            this.timerDetect.Interval = 100;
            this.listener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);       
            this.FormClosing += (obj, e) =>
            {
                this.timerDetect.Stop();
                this.timerDetect.Dispose();
                this.listener.Shutdown(SocketShutdown.Both);
                this.listener.Close();
            };                       
        }       

        private void FrmPortData_Load(object sender, EventArgs e)
        {
            var ipPoint = new IPEndPoint(Helper.MachineIP, int.Parse(Input.Trim()));
            this.listener.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
            this.listener.Bind(ipPoint);
            var output = new byte[4];
            this.listener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, output);
            //if (BitConverter.ToInt32(output, 0) != 0)
            if (output[0] + output[1] + output[2] + output[3] != 0)
                MessageBox.Show("Failed to listen port via IOControl mode!");
            else
            {
                this.listener.Blocking = false;                
                //this.listener.Listen(20480);   
                //MaxConnections = 2147483647
                this.timerDetect.Start();
            }
        }

        private void timerDetect_Tick(object sender, EventArgs e)
        {
            if (this.listener.Available > 0)
            {
                var msg = SysnAnalyzePacket(this.listener);
                if(msg != null) this.rtbMessage.Text += msg;
            }
        }        

        void acptCallback(IAsyncResult iAsyResult)
        {
            var asyResult = this.listener.BeginAccept(rcvCallback, this.listener);
            var socket = ((Socket)iAsyResult.AsyncState).EndAccept(out buffer, out transfered, iAsyResult);
            AddMessage("[{0}] Accepted {1} bytes data from {2}\r\nMessage: {3}",
                DateTime.Now.ToString("HH:mm:ss.fff"),
                transfered,
                socket.RemoteEndPoint,
                Encoding.ASCII.GetString(buffer, 0, transfered));
        }

        void rcvCallback(IAsyncResult iAsyResult)
        {
            var listener = (Socket)iAsyResult.AsyncState;
            listener.BeginReceive(buffer, 0, buffer.Length, SocketFlags.Peek, rcvCallback, listener);
            //超过1000条时清空
            if (this.rtbMessage.TextLength > 5000) this.rtbMessage.Clear();
            SocketError error;
            var rcvLength = listener.EndReceive(iAsyResult, out error);
            AddMessage("收到数据: {0}字节!", rcvLength);
            if (error != default(SocketError))
            {
                this.rtbMessage.Text += "===========接收出错:" + error.ToString();
            }
            AddMessage("[{0}] Recieved Message: {1}", DateTime.Now.ToString("HH:mm:ss.fff"), Encoding.ASCII.GetString(buffer, 0, rcvLength));
        }

        void AddMessage(string format, params object[] args)
        {
            this.rtbMessage.Text += string.Format(format, args);
        }  

/// <summary>
        /// 同步方式解析TCP数据包
        /// </summary>
        /// <param name="listener"></param>
        public static string SysnAnalyzePacket(Socket listener)
        {
            var buffer = new byte[4096];
            int transfered = listener.Receive(buffer);
            TCPPacket packet = new TCPPacket(ref buffer);
            //string Data = System.Text.RegularExpressions.Regex.Replace(System.Text.Encoding.ASCII.GetString(ip.TCP.PacketData), @"[^a-zA-Z_0-9\.\@\- ]", "");
            if (packet.ProtocolType != ProtocolType.Tcp 
------解决思路----------------------
 !packet.SourceAddress.Equals(MachineIP) && !packet.DestinationAddress.Equals(MachineIP)) 
            {
                return null;
            }
            if (packet.Error != null)
                return string.Format("\r\nError: {0} \r\nStack Trace: {1}", packet.Error.Message, packet.Error.StackTrace);
            else
                return string.Format("\r\n{0}:{1} --> {2}:{3} Message: {4}",
                    packet.SourceAddress,
                    packet.SourcePort,
                    packet.DestinationAddress,
                    packet.DestinationPort,
                    Encoding.ASCII.GetString(packet.PacketData)
                );
        }
}

还有个TCPPacket类太长就不贴了,网上有,不过有点小问题
上面的例子拿网络抓取工具对照过,没有问题
  相关解决方案