首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

求教UDP打洞高手解决思路

2013-01-25 
求教UDP打洞高手公网Server S能接受到某一公司内网主机E1发来的登陆消息,但是S返回的消息,E1无法接收。是否

求教UDP打洞高手
公网Server S能接受到某一公司内网主机E1发来的登陆消息,但是S返回的消息,E1无法接收。是否是公司网关拦截导致的?
代码如下。S端线输入SINIT,然后E1端运行E1Init,然后E1无法接受返回消息。

      static void Main(string[] args)
        {
         
                string serveraddr = "116.233.234.159";
                int port = 8600;
                long e1Addr = 0, e2Addr = 0;
                int e1Port = 0, e2Port = 0;
                System.Net.Sockets.UdpClient u = new System.Net.Sockets.UdpClient(port);
                while (true)
                {
                    string cm = Console.ReadLine();
                    if (cm == "SINIT")
                    {
                        while (true)
                        {
                            System.Net.IPEndPoint ep = new System.Net.IPEndPoint(0, 0);
                            byte[] msg = u.Receive(ref ep);
                            if (Encoding.ASCII.GetString(msg) == "Hello1")
                            {
                                e1Addr = ep.Address.Address;
                                e1Port = ep.Port;
                                for(int i=0;i<1000;i++)
                                u.Send(Encoding.ASCII.GetBytes("OK"), 2, ep);
                            }


                            else if (Encoding.ASCII.GetString(msg) == "Hello2")
                            {
                                e2Addr = ep.Address.Address;
                                e2Port = ep.Port;
                                u.Send(Encoding.ASCII.GetBytes("OK"), 2, ep);
                            }
                            else if (Encoding.ASCII.GetString(msg) == "Need2")
                            {
                                byte[] t = new byte[sizeof(long) + sizeof(int)];
                                Array.Copy(BitConverter.GetBytes(e2Addr), t, sizeof(long));
                                Array.Copy(BitConverter.GetBytes(e2Port), 0, t, sizeof(long), sizeof(int));

                                u.Send(t, t.Length, ep);
                            }
                            Console.WriteLine(Encoding.ASCII.GetString(msg));
                            System.Threading.Thread.Sleep(100);
                        }
                    }
                    else if (cm == "E1Init")
                    {
                        System.Net.IPEndPoint ep = new System.Net.IPEndPoint(ConvertToIPValue(serveraddr), port);


                        u.Send(Encoding.ASCII.GetBytes("Hello1"), 6, ep);
                        byte[] msg = u.Receive(ref ep);
                        Console.WriteLine(Encoding.ASCII.GetString(msg));
                    }
                    else if (cm == "Need2")
                    {
                        System.Net.IPEndPoint ep = new System.Net.IPEndPoint(ConvertToIPValue(serveraddr), port);
                        u.Send(Encoding.ASCII.GetBytes("Need2"), 6, ep);
                        byte[] msg = u.Receive(ref ep);
                        long addr = BitConverter.ToInt64(msg, 0);
                        int e2p = BitConverter.ToInt32(msg, sizeof(long));
                        Console.WriteLine(addr + " " + e2p);
                        ep = new System.Net.IPEndPoint(addr, e2p);
                        u.Send(Encoding.ASCII.GetBytes("Hellop from e1"), "Hellop from e1".Length, ep);
                    }
                    else if (cm == "E2Init")
                    {
                        System.Net.IPEndPoint ep = new System.Net.IPEndPoint(ConvertToIPValue(serveraddr), port);
                        u.Send(Encoding.ASCII.GetBytes("Hello2"), 6, ep);
                        byte[] msg = u.Receive(ref ep);
                        Console.WriteLine(Encoding.ASCII.GetString(msg));


                        ep = new System.Net.IPEndPoint(0, 0);
                        msg = u.Receive(ref ep);   
                        Console.WriteLine(Encoding.ASCII.GetString(msg));
                    }
                }
            }
[解决办法]
这是应为E1是通过路由器Nat转换进行上网的!E1发送给Server数据的IP是Route的ipaddres...... 
[解决办法]
路由器有几种映射模式,其中有一种貌似是动态的,打洞无效的。。。。。
网上有通过tcp方式,判断对方路由采用了哪种方式的例子
[解决办法]
UDP打洞直接用Socket不要用UdpClient,双方按以下流程打洞
A: 1.初始化UDP Socket
   2.Bind一个本地端口,注意要Bind不要Connect
   3.向外网发一个数据包(这个地址不存在也没关系,只要是外网就行了)
B: 1.初始化UDP Socket
   2.Bind一个本地端口,注意要Bind不要Connect
   3.向A的1-65535每个端口发个数据包,A收到数据包后返回一个数据包,双方并记录下对方的外网端口号
可以通过中间服务器来加快双方检测端口的速度,双方把第3步改成向中间服务器发送登录请求,并获得对方的端口,还有点要注意的就是UDP打洞无论有没有数据一定要定时的向外网发数据,否则路由会把你的洞给关了,那就又要重打了

热点排行