Beispiel #1
0
        void udpServer_DataArrival(object sender, SockEventArgs e)
        {
            if (e.Data.Length < 29) return;//如果收到非法数据包则退出
            //byte[] data = new byte[e.Count];
            //Buffer.BlockCopy(e.Buffer, 0, data, 0, e.Count);

            UDPFramePacket packet = new UDPFramePacket(e.Data);

            if (packet.type == (byte)TransmitType.Audio || packet.type == (byte)TransmitType.Video)
            {
                //客户端请求与另一客户端打洞或请求转发文件数据包到另一客户端
                IPEndPoint RemoteEP = new IPEndPoint(packet.RemoteIP, packet.Port);//获得消息接收者远程主机信息
                udpServer.Send(RemoteEP, packet.BaseData);//将远程主机信息发送给客户端
            }
            else if (packet.type == (byte)TransmitType.getRemoteEP)//客户端请求获取自己的远程主机信息 
            {
                packet.RemoteIP = e.RemoteIPEndPoint.Address;//设置客户端的远程IP
                packet.Port = e.RemoteIPEndPoint.Port;//设置客户端的远程UDP 端口
                udpServer.Send(e.RemoteIPEndPoint, packet.BaseData);//将远程主机信息发送给客户端
            }
             
        }
Beispiel #2
0
 /// <summary>
 /// 添加数据包到侦
 /// </summary>
 /// <param name="frame"></param>
 public void Add(UDPFramePacket packet)
 {
     if (!FrameComplete)
     {
         Frame.Add(packet.PacketIndex, packet);
         if (Frame.Count >= PacketCount)
             FrameComplete = true;
     }
 }
Beispiel #3
0
        /// <summary>
        /// 设置远程主机信息
        /// </summary>
        /// <param name="remoteIP">远程主机(广域网)</param>
        /// <param name="remoteLocalIP">远程主机(局域网)</param>
        public void setRemoteIP(IPEndPoint remoteLocalIP, IPEndPoint remoteIP)
        {

            #region 网络打洞互联 时间计数器
            int TimeCount = 0;
            System.Timers.Timer timer1 = new System.Timers.Timer();
            timer1.Interval = 500;
            timer1.Enabled = true;

            timer1.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e)
            {
                TimeCount++;

                if (toEP == null && TimeCount <= 20)//如果10秒后还未与对方建立联接
                {
                    UDPFramePacket packet = new UDPFramePacket();
                    packet.type = (byte)TransmitType.Penetrate;//打洞数据包
                    packet.Block = new byte[1400];
                    if (sockUDP != null && sockUDP.Listened)
                        sockUDP.Send(remoteLocalIP, packet.ToBytes());//发送一次局域网正常打洞请求

                    UDPFramePacket packet1 = new UDPFramePacket();
                    packet1.type = (byte)TransmitType.Penetrate;//打洞数据包
                    packet1.Block = new byte[512];
                    if (sockUDP != null && sockUDP.Listened)
                        sockUDP.Send(remoteLocalIP, packet1.ToBytes());//发送一次局域网小包打洞请求

                    UDPFramePacket packet2 = new UDPFramePacket();
                    packet2.type = (byte)TransmitType.Penetrate;//打洞数据包
                    packet2.Block = new byte[1400];
                    if (sockUDP != null && sockUDP.Listened)
                        sockUDP.Send(remoteIP, packet2.ToBytes());//发送一次广域网打洞请求

                    UDPFramePacket packet3 = new UDPFramePacket();
                    packet3.type = (byte)TransmitType.Penetrate;//打洞数据包
                    packet3.Block = new byte[512];
                    if (sockUDP != null && sockUDP.Listened)
                        sockUDP.Send(remoteIP, packet3.ToBytes());//发送一次广域网小包打洞请求
                }
                else
                {
                    //终止发送,并触发获得主机事件
                    timer1.Enabled = false;
                    timer1.Dispose();
                    timer1 = null;
                    if (toEP != null)//如果已与对方打洞成功并建立连接
                    {
                        if (TimeCount <= 10)
                        {
                            connectedType = ConnectedType.UDPLocal;//标明是局域网连接
                            Console.WriteLine("局域网打洞成功,MTU=" + mtu.ToString() + ",打洞次数:" + TimeCount.ToString());
                        }
                        else
                        {
                            connectedType = ConnectedType.UDPRemote;//标明是广域网连接
                            Console.WriteLine("广域网打洞成功,MTU=" + mtu.ToString() + ",打洞次数:" + TimeCount.ToString());
                        }
                    }
                    else//打洞超时,数据只能通过服务器中转
                    {
                        Console.WriteLine("局域网打洞不成功,打洞次数::" + TimeCount.ToString());
                        mtu = 1400;
                        toEP = remoteIP;//将对方的广域网远程主机信息记录下来
                    }

                    OnTransmitConnected();//触发连接建立事件
                }
            };
            #endregion
        }
Beispiel #4
0
        /// <summary>
        /// 开始
        /// </summary>
        public void Start()
        {
            if (sockUDP != null) return;//如果已经初始化套接字 ,则退出

            if (sockUDP == null)
            {
                sockUDP = new SockUDP();
                sockUDP.DataArrival += new SockUDP.UDPEventHandler(sockUDP_DataArrival);
                sockUDP.Listen(0);//随机侦听
            }

            IPEndPoint myLocalEP = null;
            System.Net.IPAddress[] ips = System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName());//获得本机局域网IPV4地址
            for (int i = ips.Length - 1; i >= 0; i--)
            {
                if (ips[i].GetAddressBytes().Length == 4)
                {
                    myLocalEP = new IPEndPoint(ips[i], sockUDP.ListenPort);//获得本机局域网地址
                    break;
                }
            }

            UDPFramePacket packet = new UDPFramePacket();
            packet.type = (byte)TransmitType.getRemoteEP;//获得公网主机信息
            packet.PacketCount = 1;
            sockUDP.Send(ServerEP, packet.BaseData);

            #region 主机信息获取 时间计数器
            int TimeCount = 0;
            System.Timers.Timer timer1 = new System.Timers.Timer();
            timer1.Interval = 500;
            timer1.Enabled = true;
            timer1.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e)
            {
                if (myRemoteEP == null && TimeCount < 10)//如果还未获得本机远程主机信息
                {
                    sockUDP.Send(ServerEP, packet.BaseData);//每隔500毫秒发送一次请求
                }
                else//如果三秒内已经获得主机信息或三秒钟后未获得主机信息
                {
                    //终止发送,并触发获得主机事件
                    timer1.Enabled = false;
                    timer1.Dispose();
                    timer1 = null;
                    if (myRemoteEP == null)//如果超时未获得本机远程主机信息
                        myRemoteEP = myLocalEP;//假设本机的远程IP等于本地IP
                    OnGetIPEndPoint(this, myLocalEP, myRemoteEP);//触发获取本机主机事件
                }
                TimeCount++;
            };
            #endregion


            ///开始组包线程
            videoThread = new System.Threading.Thread(new System.Threading.ThreadStart(VideoDecoderThread));
            videoThread.Start();
        }
Beispiel #5
0
        /// <summary>
        /// 发送数据包
        /// </summary>
        /// <param name="type"></param>
        /// <param name="data"></param>
        public void sendData(TransmitType type, byte[] data)
        {
            if (data == null || data.Length == 0) return;
            SendTimestamp++;
            UDPFramePacket packet = new UDPFramePacket();
            packet.type = (byte)type;
            packet.Timestamp = SendTimestamp;
            packet.Block = data;
            send(packet.ToBytes());
            return;
            if (data.Length <= mtu)
            {
                packet.PacketCount = 1;
                packet.Block = data;
                send(packet.ToBytes());
                Console.WriteLine(packet.type.ToString() + ":" + packet.ToBytes().Length.ToString());
            }
            else
            {
                int count = data.Length / mtu;
                if (data.Length % mtu != 0)
                    count += 1;
                int offSet = 0;
                byte[] block = new byte[mtu];
                for (int i = 0; i < count; i++)
                {
                    packet.PacketCount = count;
                    packet.PacketIndex = i;
                    if (offSet + mtu > data.Length)
                        block = new byte[data.Length - offSet];//要发送的缓冲区

                    Buffer.BlockCopy(data, offSet, block, 0, block.Length);
                    packet.Block = block;
                    send(packet.ToBytes());
                    offSet += mtu;
                    Console.WriteLine(  packet.type.ToString() +":"+ packet.ToBytes().Length.ToString());
                }
            }
        }
Beispiel #6
0
        private void sockUDP_DataArrival(object sender, SockEventArgs e)
        {
            if (e.Data.Length < 29) return;
            UDPFramePacket packet = new UDPFramePacket(e.Data);//获得一侦数据的一个包

            if (packet.type == (byte)TransmitType.Video || packet.type == (byte)TransmitType.Audio)//收到音频视频数据包 
            {
                if (packet.type == (byte)TransmitType.Video)//触发视频数据到达事件
                    OnRecVideoData(this, packet.Block );
                else if (packet.type == (byte)TransmitType.Audio)//触发音频数据到达事件
                    OnRecAudioData(this, packet.Block);

                return;

                if (packet.PacketCount >0 && packet.PacketCount <33)//最大32个数据包
                {
                    lock (ReceiverFrames)
                    {
                        if (ReceiverFrames.ContainsKey(packet.Timestamp))//如果侦已经存在
                        {
                            frame f = ReceiverFrames[packet.Timestamp];
                            f.Add(packet);//将包添加到侦
                        }
                        else
                        {
                            frame f = new frame();//创建侦
                            f.Add(packet);//将包添加到侦
                            f.dateTime = DateTime.Now;
                            f.type = packet.type;//设置侦类型
                            f.Timestamp = packet.Timestamp;//设置时间戳
                            f.PacketCount = packet.PacketCount;//设置侦的包总数
                            ReceiverFrames.Add(packet.Timestamp, f);//添加侦
                        }
                    }
                }
            }
            else if (packet.type == (byte)TransmitType.Penetrate)//收到另一客户端请求打洞 
            {
                toEP = e.RemoteIPEndPoint;
                if (packet.Block.Length > mtu)//确定MTU值
                    mtu = packet.Block.Length;
                if (connectedType == ConnectedType.None)//如果还未连接,继续打洞
                    sockUDP.Send(toEP, packet.BaseData);//告之对方收到打洞包并向对方打洞 
            }
            else if (packet.type == (byte)TransmitType.getRemoteEP)//收到自己的远程主机信息 
            {
                if (myRemoteEP == null)
                    myRemoteEP = new IPEndPoint(packet.RemoteIP, packet.Port);//设置自己的远程主机信息
            }
        }