通訊協定的分層規定
把使用者應用程式層作為最高層,把物理通訊線路作為最底層,期間的協議處理分為若干層,規定每層處理的任務,也規定每層的介面標準。
目前分層國際的標準有兩種:OSI參考模型和TCP/IP參考模型
一台機器想把一句話送出去的流程
需要從應用程式層一步步的把資料封裝傳遞到最底層直到物理層的底層轉換為二進位0100101010然後在送出去
送出去之後 對方最底層接收到0101010101然後一步步的翻譯到應用程式層 這是資料在網路之間傳輸的一個過程。
底層對我們透明 看似是應用程式層之間通訊,並不是。
HTTPS加密
在使用HTTPS時,所有的HTTP請求和響應資料在發送到網路之前,都要進行加密。
HTTPS在HTTP下面提供了一個傳輸級的密碼安全層SSL/TSL(Transport Layer Security)。即在應用程式層和傳輸層之間加了一個安全層。
對稱秘鑰的加密技術:編/解碼時使用相同秘鑰的演算法。
在對稱式加密技術中,發送端和接收端要共用相同的秘鑰K才能進行通訊。發送端用共用的秘鑰加密報文,並將得到的密文發送給接收端。
接收端接收到密文,並對其應用解密函數和相同的共用秘鑰,恢複出原始的明文。
對稱秘鑰加密技術的缺點之一就是寄件者和接受者在互相對話之前,一定要有一個共用的保密秘鑰。
流行的對稱秘鑰密碼編譯演算法包括: DES Triple-DES RC2和RC4。64為的秘鑰應該是大多數公司所採用的。
不對稱秘鑰加密系統:編/解碼使用不同秘鑰的演算法。
非對稱式加密使用兩個秘鑰,一個用來對主機報文編碼,另一個用來對主機報文解碼。
編碼秘鑰是眾所周知的,只有主機才知道私人的解密秘鑰。
通過公開秘鑰的加密技術,全球所有的電腦使用者就都可以使用安全性通訊協定了,其中RSA演算法是一個比較流行的公開秘鑰的密碼編譯演算法。
數位簽章
數位簽章是附加在報文上特殊加密校正碼,使用數位簽章有以下兩個好處
簽名可以證明是作者編寫了這條報文
簽名可以防止報文被篡改。如果有惡意攻擊者在報文傳輸過程中對其進行了修改,校正和就不匹配了。
數位簽章通常是用非對稱公開秘鑰技術產生的。因為只有所有者才知道其私人秘鑰,所以可以將作者的私人秘鑰當做一種指紋使用。
用認證對伺服器進行認證。
通過HTTPS建立了一個安全的Web事物之後,瀏覽器都會自動擷取所串連伺服器的數位憑證。
瀏覽器收到認證時,會對簽名頒發機構進行檢查。如果這個機構是個很有權威的公用簽名機構,瀏覽器可以知道其公開秘鑰了(瀏覽器會預裝很多簽名頒發機構的認證)。
參考文章 78485665
Socket實現網路通訊
啟動一個TCPServer
public class TCPServer { public static void main(String[] args) throws Exception { ServerSocket ss = new ServerSocket(6666); while(true) { Socket s = ss.accept(); System.out.println("a client connect!"); DataInputStream dis = new DataInputStream(s.getInputStream()); System.out.println(dis.readUTF()); dis.close(); s.close(); } }}
View Code
利用DataInputStream 的一些方法不需要把要讀寫的資料進行位元組數組來迴轉換(inputStream只提供了讀寫位元組和位元組數組的方法).
通常資料輸出資料流按照一定的格式輸出,在通過資料輸入流按照一定的格式輸入,這樣可以方便的對資料進行處理。
如:通過writeUTF()把一個Unicode字串寫進去,可以使用readUTF()直接讀進來。
tip:String str = "abc";等效於: char data[] = {'a', 'b', 'c'}; String str = new String(data);
啟動一個TCPClient
public class TCPClient { public static void main(String[] args) throws Exception { Socket s = new Socket("127.0.0.1", 6666); OutputStream os = s.getOutputStream(); DataOutputStream dos = new DataOutputStream(os); Thread.sleep(30000); dos.writeUTF("hello server!"); dos.flush(); dos.close(); s.close(); }}
View Code
上面雖然實現了用戶端與Server端的通訊,但是缺點也很明顯。
- 在使用IO和Socket構造網路服務時 接收串連:accept(),接收請求資料,發送響應資料都可能引起阻塞的操作。、
- 線程從Socket輸入資料流讀資料時,如果沒有足夠的資料就會進入阻塞狀態,直到讀夠了足夠的資料,或者達到輸入資料流的末尾,或者出現了異常,才能從輸入資料流的read()方法返回或異常中斷。
輸入資料流中有多少資料才算足夠呢?這要看執行read()方法的類型。
int read()只要輸入資料流中有一個位元組就算足夠。
int read(byte[] buff) 只要輸入資料流中的位元組數目與參數buff數組的長度相同,就算足夠。(這個方法的好處 可以看看適配器設計模式中的知識點)
String readLine() 只要輸入資料流中有一行字串就算足夠(BufferReader類中才有此方法)。
Socket網路通訊改進
以上兩個阻塞式的方法住我們的當前線程。伺服器可以使用多線程來處理阻塞I/O,儘管能滿足同時響應多個客戶請求的需求,但是增加了java虛擬機器調度線程的負擔。
在阻塞模式下,
- read()方法會爭取讀到n個位元組,如果輸入資料流中不足n個位元組,就進入阻塞狀態,直到讀取了n個位元組,或者讀到了輸入資料流末尾,或者出現了I/O異常。
- socket.accept()方法如果沒有接收到串連,也會一直等待
在非阻塞模式下
- read()方法奉行能讀到多少資料就讀到多少資料的原則。read()方法讀取當前通道中的可讀資料,有可能不足n個位元組,或者為0個位元組,read()方法總會立刻返回。而不會等到讀取了n個位元組才返回,read()方法返回實際上讀入的位元組數。SocketChannel extends AbstractSelectableChannel 類的中 int read(ByteBuffer dst)方法是非阻塞式的。
- ServerSocketChannel或SockeChannel通過register()方法向Selector註冊事件時,register()方法會建立一個SelectionKey對象,這個SelectionKey對象是跟蹤註冊事件的控制代碼。在SelectionKey對象有效期間,Selector會一直監控與SelectorKey對象相關的事件,如果事件發生,就會把SelectionKey對象加入到Selector-keys集合中。