一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

C#代碼實(shí)現(xiàn)TCP穿透(打洞)

 _明心見性_ 2021-12-07

?內(nèi)網(wǎng)之間實(shí)現(xiàn)TCP通訊需要用到內(nèi)網(wǎng)穿透技術(shù),具體原理網(wǎng)上都有,參考:

https://blog.csdn.net/leisure512/article/details/4900191

https://blog.csdn.net/aaron133/article/details/79206257

TCP穿透成功的條件需要兩邊網(wǎng)絡(luò)都是錐形NAT(或者至少一端網(wǎng)絡(luò)是錐形NAT),具體可以參考

https://blog.csdn.net/h_armony/article/details/45167975

里面有給出各種NAT說明:

有公網(wǎng)IP的寬帶:比如聯(lián)通的ADSL,這類寬帶會給每個(gè)用戶分配一個(gè)公網(wǎng)IP,所以其NAT類型取決于用戶所選用的路由器,大部分家用路由器都是端口限制錐型NAT;

無公網(wǎng)IP的寬帶:比如寬帶通,這類寬帶給用戶分配的是局域網(wǎng)IP,連接公網(wǎng)的NAT是運(yùn)營商的,一般都是對稱型NAT;

移動互聯(lián)網(wǎng):跟“無公網(wǎng)IP的寬帶”類似,分配給手機(jī)的是局域網(wǎng)IP,出口基本都是對稱型NAT;

大公司路由器:大部分都把路由器配置成對稱型NAT。

這邊使用VS2010 C#實(shí)現(xiàn):

服務(wù)端代碼:

static void Main(string[] args)
{
int port = 555;
IPEndPoint ipe = new IPEndPoint(IPAddress.Any, port);
Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sSocket.Bind(ipe);
sSocket.Listen(100);
Console.WriteLine(“監(jiān)聽已經(jīng)打開,請等待”);

        while (true)
        {
            Socket serverSocket1 = sSocket.Accept();
            Console.WriteLine('連接已經(jīng)建立');
            string recStr = '';
            byte[] recByte = new byte[4096];
            int bytes = serverSocket1.Receive(recByte);
            IPEndPoint ep1 = (IPEndPoint)serverSocket1.RemoteEndPoint;
            Console.WriteLine(' from {0}', ep1.ToString()); 
            recStr = Encoding.ASCII.GetString(recByte, 0, bytes);
            Console.WriteLine('客戶端1:{0}', recStr);

            Socket serverSocket2 = sSocket.Accept();
            bytes = serverSocket2.Receive(recByte);
            IPEndPoint ep2 = (IPEndPoint)serverSocket2.RemoteEndPoint;
            Console.WriteLine(' from {0}', ep2.ToString());
            recStr = Encoding.ASCII.GetString(recByte, 0, bytes);
            Console.WriteLine('客戶端2:{0}', recStr);


            byte[] sendByte =Encoding.ASCII.GetBytes(ep1.ToString() + ':' + ep2.ToString());  
            serverSocket1.Send(sendByte, sendByte.Length, 0);

            sendByte = Encoding.ASCII.GetBytes(ep2.ToString() + ':' + ep1.ToString());  
            serverSocket2.Send(sendByte, sendByte.Length, 0);

            serverSocket1.Close();
            serverSocket2.Close();
        } 
          
    } 

功能:兩邊客戶端連接服務(wù)器后將映射的外網(wǎng)IP和端口號傳給雙方。

客戶端代碼

static void Main(string[] args)
{
string host = “115.21.X.X”;//服務(wù)端IP地址
int port = 555;
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//設(shè)置端口可復(fù)用
clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//連接服務(wù)端
clientSocket.Connect(host, port);
Console.WriteLine(“Connect:” + host + ' ' + port);

        string data = 'hello,Server!';
        clientSocket.Send(Encoding.ASCII.GetBytes(data));
        Console.WriteLine('Send:' + data);
        byte[] recBytes = new byte[100];
        //獲取到雙方的ip及端口號
        int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0);
       string result = Encoding.ASCII.GetString(recBytes, 0, bytes);
       Console.WriteLine('Recv:' +result);
       clientSocket.Close();

       string[] ips = result.Split(':'); 
       int myPort = Convert.ToInt32(ips[1]);
       string otherIp = ips[2];
       int otherPort = Convert.ToInt32(ips[3]);


       Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
       mySocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        //綁定到之前連通過的端口號
       IPEndPoint ipe = new IPEndPoint(IPAddress.Any, Convert.ToInt32(myPort));
       mySocket.Bind(ipe);
        //嘗試5次連接
       for (int j = 0; j < 5; j++)
       {
           try
           {
               mySocket.Connect(otherIp, otherPort);
               Console.WriteLine('Connect:成功{0},{1}', otherIp,otherPort);
               break;
           }
           catch (Exception)
           {
               Console.WriteLine('Connect:失敗');
                // otherPort++;//如果是對稱NAT,則有可能客戶端的端口號已經(jīng)改變,正常有規(guī)律的應(yīng)該是順序加1,可以嘗試+1再試(我使用手機(jī)熱點(diǎn)連接的時(shí)候端口號就變成+1的了)除非是碰到隨機(jī)端口,那就不行了。
           }

       }
       while (true)
       {
           mySocket.Send(Encoding.ASCII.GetBytes('hello,the other client!'));

           byte[] recv = new byte[4096];
           int len = mySocket.Receive(recv, recv.Length, 0);
           result = Encoding.ASCII.GetString(recv, 0, len);
           Console.WriteLine('recv :' + result);

           Thread.Sleep(1000); 
       }

}

另一邊客戶端也一樣。連接服務(wù)器后,可以綁定之前的端口號復(fù)用,但如果碰到一端是對稱NAT時(shí)每次使用端口號會不一樣時(shí),這樣就得通過預(yù)測下次可能使用的端口號來連通。如:使用手機(jī)熱點(diǎn)網(wǎng)絡(luò)連接服務(wù)器時(shí),獲取到它使用的端口號是56324,等到下一次客戶端互相連接使用56325才連上。
?

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产精品视频一级香蕉| 中文字幕在线五月婷婷| 亚洲性生活一区二区三区| 九七人妻一区二区三区| 不卡免费成人日韩精品| 欧美韩日在线观看一区 | 人妻一区二区三区多毛女| 国产欧美一区二区三区精品视| 日韩欧美综合在线播放| 国产亚洲视频香蕉一区| 91在线国内在线中文字幕| 国产av乱了乱了一区二区三区| 欧美日韩国产精品黄片| 能在线看的视频你懂的| 人妻露脸一区二区三区| 亚洲一区二区三区免费的视频| 欧美激情一区=区三区| 老司机精品视频免费入口| 欧美日韩综合免费视频| 激情爱爱一区二区三区| 亚洲精品成人福利在线| 亚洲一区二区三在线播放| 亚洲淫片一区二区三区| 中文字幕精品一区二区年下载| 亚洲综合伊人五月天中文| 欧美国产亚洲一区二区三区| 在线观看日韩欧美综合黄片| 国产亚洲欧美另类久久久| 亚洲欧美黑人一区二区| 中文人妻精品一区二区三区四区 | 一本色道久久综合狠狠躁| 国产又粗又猛又爽色噜噜| 精品欧美日韩一区二区三区| 国产性色精品福利在线观看| 亚洲夫妻性生活免费视频| 日本在线 一区 二区| 国产精品二区三区免费播放心| 国产免费操美女逼视频| 亚洲精品中文字幕欧美| 亚洲成人久久精品国产| 东京热加勒比一区二区三区|