整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          JavaScript-使用node實(shí)現(xiàn)簡單登錄功能

          JavaScript-使用node實(shí)現(xiàn)簡單登錄功能

          編最近對Node特別感興趣,所以就趁著周末的時間搭了一個簡單的登錄注冊的一個小后臺。

          前端部分

          這部分主要是,從前端發(fā)送ajax請求到后臺,如果返回參數(shù)是成功,則登錄,否則,打印相關(guān)參數(shù);

          代碼

          這是界面

          后臺部分

          后臺用的是Node.js,框架用的express,數(shù)據(jù)庫用的mysql;

          數(shù)據(jù)庫結(jié)構(gòu)

          表結(jié)構(gòu)

          node代碼如下:

          express是node的基礎(chǔ)框架,這里邊有坑的地方是:返回值的時候,必須返回對象。

          掌握一門后臺語言,對于現(xiàn)在的前端工作來說,越來越重要了,代碼之路,漫漫求索,共勉之,兄弟姐妹們。

          于網(wǎng)絡(luò)用戶來說,一定都經(jīng)歷過出門在外無法直接在異地訪問公司的ERP系統(tǒng)、或是難以部署異地遠(yuǎn)程桌面,因此心急如焚的情況;對于企業(yè)來說,無論是財(cái)務(wù)管理軟件難以將分店信息同步到總部進(jìn)行統(tǒng)計(jì)匯總、還是員工出差在外或在家里就不能訪問企業(yè)內(nèi)部辦公系統(tǒng),都極大地影響了公司整體效率;對于個人開發(fā)者來說,微信小程序或者在線支付系統(tǒng)等開發(fā)環(huán)境往往需要一個可以環(huán)境進(jìn)行調(diào)試,不然的話,難以進(jìn)行開發(fā)調(diào)試。

          諸如此類的難題眾多,但解決方法其實(shí)很簡單,那就是使用軟件或者自己手寫一個,可以支持訪問我的電腦上的微信支付接口,從而實(shí)現(xiàn)這一系列的簡易操作。目前國內(nèi)這方面企業(yè)級的服務(wù)商有**殼和神卓互聯(lián),我接觸過很多公司在用,**殼的技術(shù)是PHTunnel ,神卓互聯(lián)用的是Wangooe Tunnel技術(shù),這里就介紹神卓互聯(lián)的,接下來就介紹和分析這款軟件的用法和技術(shù)要點(diǎn)。如果沒有接觸過這方面技術(shù)的同學(xué)可以看一下這個圖:

          首先用法很簡單,就是在界面上創(chuàng)建一條映射規(guī)則,填寫應(yīng)用名稱和要連接的內(nèi)網(wǎng)應(yīng)用主機(jī)地址和端口號,

          填寫自己要穿透的應(yīng)用名稱和端口號,如果需要獲取原訪問者IP最好是選擇Web應(yīng)用。提交提交就可以了。

          例如我需要發(fā)布一個Tomcat應(yīng)用,訪問端口號是7070,那么應(yīng)用名稱填寫tomcat,內(nèi)網(wǎng)主機(jī)填寫127.0.0.1,內(nèi)網(wǎng)端口填7070點(diǎn)提交就可以。

          首先新建一個web項(xiàng)目

          新建login.jsp登陸文件,內(nèi)容如下:

          <%@ page language="java" contentType="text/html; charset=UTF-8"
              pageEncoding="UTF-8"%>
          <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
          <html>
          <head>
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
          <title>登錄系統(tǒng)</title>
          <style type="text/css">
          table td{font: 14px/1.5 'Microsoft YaHei',arial,tahoma,\5b8b\4f53,sans-serif;}
          </style>
          </head>
          <body>
          <table>
          <tr><td>用戶名</td><td><input type="text"></td></tr>
          <tr><td>密碼</td><td><input type="text"></td></tr>
          <tr><td> </td><td><input type="submit" value="登錄"></td></tr>
          </table>
          </body>
          </html>

          先在本地運(yùn)行,看項(xiàng)目是否可以正常運(yùn)行:

          本地運(yùn)行沒有問題,可以正常打開,接下來就試一下外網(wǎng)訪問

          打開神卓互聯(lián)軟件主界面,右鍵選擇外網(wǎng)訪問

          如果需要綁定域名訪問的話也很簡單,這里不多說。

          接下來就分析是如何做到將請求轉(zhuǎn)發(fā)到內(nèi)網(wǎng)因?yàn)橛址祷亟o訪問客戶端的。



          InetAddress

          //獲取本機(jī)的InetAddress實(shí)例
          InetAddress address=InetAddress.getLocalHost();
          address.getHostName();//獲取計(jì)算機(jī)名
          address.getHostAddress();//獲取IP地址
          byte[] bytes=address.getAddress();//獲取字節(jié)數(shù)組形式的IP地址,以點(diǎn)分隔的四部分
           
          //獲取其他主機(jī)的InetAddress實(shí)例
          InetAddress address2=InetAddress.getByName("其他主機(jī)名");
          InetAddress address3=InetAddress.getByName("IP地址");

          URL類

          //創(chuàng)建一個URL的實(shí)例
          URL baidu=new URL("http://www.baidu.com");
          URL url=new URL(baidu,"/index.html?username=tom#test");//?表示參數(shù),#表示錨點(diǎn)
          url.getProtocol();//獲取協(xié)議
          url.getHost();//獲取主機(jī)
          url.getPort();//如果沒有指定端口號,根據(jù)協(xié)議不同使用默認(rèn)端口。此時getPort()方法的返回值為 -1
          url.getPath();//獲取文件路徑
          url.getFile();//文件名,包括文件路徑+參數(shù)
          url.getRef();//相對路徑,就是錨點(diǎn),即#號后面的內(nèi)容
          url.getQuery();//查詢字符串,即參數(shù)

          以下就是P2P打洞核心代碼(TCP)

          假設(shè)現(xiàn)在有以下3臺機(jī)器:

          外網(wǎng)機(jī)器,IP:121.56.21.85 , 以下簡稱“主機(jī)A”

          處在內(nèi)網(wǎng)1下的機(jī)器,外網(wǎng)IP:106.116.5.45 ,內(nèi)網(wǎng)IP:192.168.1.10, 以下簡稱“主機(jī)1”

          處在內(nèi)網(wǎng)2下的機(jī)器,外網(wǎng)IP:104.128.52.6 ,內(nèi)網(wǎng)IP:192.168.0.11,以下簡稱“主機(jī)2”

          很顯然內(nèi)網(wǎng)的兩臺機(jī)器不能直接連接,我們現(xiàn)在要實(shí)現(xiàn)的是借助外網(wǎng)機(jī)器,讓兩臺內(nèi)網(wǎng)機(jī)器進(jìn)行tcp直連通訊。

          實(shí)現(xiàn)過程如下:

          1、主機(jī)A啟動服務(wù)端程序,監(jiān)聽端口8888,接受TCP請求。

          2、啟動主機(jī)1的客戶端程序,連接主機(jī)A的8888端口,建立TCP連接。

          3、啟動主機(jī)2的客戶端程序,連接主機(jī)A的8888端口,建立TCP連接。

          4、主機(jī)2發(fā)送一個命令告訴主機(jī)A,我要求與其他設(shè)備進(jìn)行連接,請求協(xié)助進(jìn)行穿透。

          5、主機(jī)A接收到主機(jī)2的命令之后,會返回主機(jī)1的外網(wǎng)地址和端口給主機(jī)2,同時把主機(jī)2的外網(wǎng)地址和端口發(fā)送給主機(jī)1。

          6、主機(jī)1和主機(jī)2在收到主機(jī)A的信息之后,同時異步發(fā)起對對方的連接。

          7、在與對方發(fā)起連接之后,監(jiān)聽本地與主機(jī)A連接的端口(也可以在發(fā)起連接之前),(由于不同的操作系統(tǒng)對tcp的實(shí)現(xiàn)不盡相同,有的操作系統(tǒng)會在連接發(fā)送之后,把對方的連接當(dāng)作是回應(yīng),即發(fā)出SYN之后,把對方發(fā)來的SYN當(dāng)作是本次SYN的ACK,這種情況就不需要監(jiān)聽也可建立連接,本文的代碼所在測試環(huán)境就不需要監(jiān)聽,測試環(huán)境為:服務(wù)器centos 7.3, 內(nèi)網(wǎng)1 win10,內(nèi)網(wǎng)2 win10和centos7.2都測試過)。

          8、主機(jī)1和主機(jī)2成功連上,可以關(guān)閉主機(jī)A的服務(wù),主機(jī)1和主機(jī)2的連接依然會持續(xù)生效,不關(guān)閉就形成了一個3方直連的拓?fù)渚W(wǎng)狀結(jié)構(gòu)網(wǎng)絡(luò)。

          服務(wù)器端代碼:

          package org.inchain.p2p;
           
          import java.io.IOException;
          import java.net.ServerSocket;
          import java.net.Socket;
          import java.util.ArrayList;
          import java.util.List;
           
          /**
           * 外網(wǎng)端服務(wù),穿透中繼
           * 
           * @author ln
           *
           */
          public class Server {
           
          	public static List<ServerThread> connections=new ArrayList<ServerThread>();
           
          	public static void main(String[] args) {
          		try {
          			// 1.創(chuàng)建一個服務(wù)器端Socket,即ServerSocket,指定綁定的端口,并監(jiān)聽此端口
          			ServerSocket serverSocket=new ServerSocket(8888);
          			Socket socket=null;
          			// 記錄客戶端的數(shù)量
          			int count=0;
          			System.out.println("***服務(wù)器即將啟動,等待客戶端的連接***");
          			// 循環(huán)監(jiān)聽等待客戶端的連接
          			while (true) {
          				// 調(diào)用accept()方法開始監(jiān)聽,等待客戶端的連接
          				socket=serverSocket.accept();
          				// 創(chuàng)建一個新的線程
          				ServerThread serverThread=new ServerThread(socket);
          				// 啟動線程
          				serverThread.start();
           
          				connections.add(serverThread);
           
          				count++;// 統(tǒng)計(jì)客戶端的數(shù)量
          				System.out.println("客戶端的數(shù)量:" + count);
          			}
          			
          		} catch (IOException e) {
          			e.printStackTrace();
          		}
          	}
          }
          package org.inchain.p2p;
           
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.io.PrintWriter;
          import java.net.InetAddress;
          import java.net.Socket;
           
          /**
           * 外網(wǎng)端服務(wù)多線程處理內(nèi)網(wǎng)端連接
           * 
           * @author ln
           *
           */
          public class ServerThread extends Thread {
          	// 和本線程相關(guān)的Socket
          	private Socket socket=null;
          	private BufferedReader br=null;
          	private PrintWriter pw=null;
          	
           
          	public ServerThread(Socket socket) throws IOException {
          		this.socket=socket;
          		this.br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
          		this.pw=new PrintWriter(socket.getOutputStream());
          	}
           
          	// 線程執(zhí)行的操作,響應(yīng)客戶端的請求
          	public void run() {
           
          		InetAddress address=socket.getInetAddress();
          		System.out.println("新連接,客戶端的IP:" + address.getHostAddress() + " ,端口:" + socket.getPort());
           
          		try {
          			pw.write("已有客戶端列表:" + Server.connections + "\n");
           
          			// 獲取輸入流,并讀取客戶端信息
          			String info=null;
          			
          			while ((info=br.readLine()) !=null) {
          				// 循環(huán)讀取客戶端的信息
          				System.out.println("我是服務(wù)器,客戶端說:" + info);
           
          				if (info.startsWith("newConn_")) {
          					//接收到穿透消息,通知目標(biāo)節(jié)點(diǎn)
          					String[] infos=info.split("_");
          					//目標(biāo)節(jié)點(diǎn)的外網(wǎng)ip地址
          					String ip=infos[1];
          					//目標(biāo)節(jié)點(diǎn)的外網(wǎng)端口
          					String port=infos[2];
          					
          					System.out.println("打洞到 " + ip + ":" + port);
          					
          					for (ServerThread server : Server.connections) {
          						if (server.socket.getInetAddress().getHostAddress().equals(ip)
          								&& server.socket.getPort()==Integer.parseInt(port)) {
          							
          							//發(fā)送命令通知目標(biāo)節(jié)點(diǎn)進(jìn)行穿透連接
          							server.pw.write("autoConn_" + socket.getInetAddress().getHostAddress() + "_" + socket.getPort()
          									+ "\n");
          							server.pw.flush();
          							
          							break;
          						}
          					}
          				} else {
          					// 獲取輸出流,響應(yīng)客戶端的請求
          					pw.write("歡迎您!" + info + "\n");
          					// 調(diào)用flush()方法將緩沖輸出
          					pw.flush();
          				}
          				
          			}
          		} catch (Exception e) {
          			e.printStackTrace();
          		} finally {
          			System.out.println("客戶端關(guān)閉:" + address.getHostAddress() + " ,端口:" + socket.getPort());
          			Server.connections.remove(this);
          			// 關(guān)閉資源
          			try {
          				if (pw !=null) {
          					pw.close();
          				}
          				if (br !=null) {
          					br.close();
          				}
          				if (socket !=null) {
          					socket.close();
          				}
          			} catch (IOException e) {
          				e.printStackTrace();
          			}
          		}
          	}
           
          	@Override
          	public String toString() {
          		return "ServerThread [socket=" + socket + "]";
          	}
          }

          最后附上測試方法和運(yùn)行效果:

          使用方法:

          1、在服務(wù)器啟動Server。

          2、在客戶端1啟動Client,輸入notwait命令,等待服務(wù)器通知打洞。

          3、在客戶端2啟動Client,輸入conn命令,然后輸入服務(wù)器返回的客戶端1的外網(wǎng)ip和端口,接下來就會自動完成連接。

          運(yùn)行效果:

          客戶端1運(yùn)行結(jié)果 (穿透成功之后,客戶端會把穿透對方返回的內(nèi)容發(fā)送給服務(wù)器,服務(wù)器再返回)

          客戶端1使用netstat查看的網(wǎng)絡(luò)連接

          客戶端2的運(yùn)行結(jié)果

          客戶端2使用netstat查看的網(wǎng)絡(luò)連接

          可以看到客戶端2對應(yīng)的端口不同,那是因?yàn)殡娦臢AT的問題,本地獲取的Ip是電信10開頭的內(nèi)網(wǎng)地址,相當(dāng)于在客戶端2的上層還進(jìn)行了一次中繼。

          s:由于沒有對稱型的NAT設(shè)備,無法做深入研究,對稱型設(shè)備的端口太難猜測,穿透成功概率很小。

          team登錄不上/網(wǎng)頁打不開無法加載怎么辦 最新解決方法分享

          Steam國服和國際服啊,它們還是有區(qū)別的。國服Steam有個新名字,叫蒸汽平臺,因?yàn)榉?wù)器就在咱們國內(nèi),所以網(wǎng)頁打開速度飛快,基本不會出錯。


          主站蜘蛛池模板: 国产成人精品a视频一区| 色屁屁一区二区三区视频国产| 麻豆AV无码精品一区二区| 内射少妇一区27P| 国产精品一区视频| 日本中文字幕一区二区有码在线| 91视频一区二区三区| 国产主播一区二区| 国产亚洲3p无码一区二区| 色一乱一伦一区一直爽| 国模精品一区二区三区视频| 亚洲一区二区成人| 蜜桃无码AV一区二区| 国产一区二区电影在线观看| 东京热无码av一区二区| 亚洲A∨精品一区二区三区| 四虎在线观看一区二区| 亚洲综合无码一区二区痴汉| 亚洲av成人一区二区三区| 人妻无码视频一区二区三区| 免费视频精品一区二区三区| 精品一区二区三区在线视频| 日产一区日产2区| 国产成人一区二区三区视频免费 | 五十路熟女人妻一区二区| 亚洲国产一区在线观看| 无码播放一区二区三区| 一区二区三区视频| 国产精品电影一区二区三区| 日韩一区二区在线免费观看| 美女视频免费看一区二区| 亚洲国模精品一区| 日本一区二区三区精品中文字幕| 无码乱人伦一区二区亚洲一| 亚洲一区无码中文字幕乱码| 久久精品免费一区二区喷潮| 成人一区二区三区视频在线观看 | 无码人妻精品一区二区三 | 日本美女一区二区三区 | 99久久人妻精品免费一区| 久久4k岛国高清一区二区|