/// <summary> /// 添加数据包到侦 /// </summary> /// <param name="frame"></param> public void Add(UDPFramePacket packet) { if (!FrameComplete) { Frame.Add(packet.PacketIndex, packet); if (Frame.Count >= PacketCount) { FrameComplete = true; } } }
/// <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()); } } }
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); //将远程主机信息发送给客户端 } }
/// <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 }
/// <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(); }
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);//设置自己的远程主机信息 } } }