什麼是網絡?java
在計算機領域中,網絡是信息傳輸、接受、共享的虛擬平臺。編程
經過它把各個點、面、體的信息聯繫到一塊兒,從而實現這些資源的共享。數組
什麼是網絡編程?服務器
網絡編程從大的方面就是說對信息的發送接收。網絡
經過操做相應API調度計算機資源硬件,而且利用管道(網線)進行數據交互的過程。併發
更爲具體的涉及:網絡模型、套接字、數據包。異步
互聯網的本質就是一系列的網絡協議,這個協議就叫OSI協議(一系列協議),按照功能不一樣,分工不一樣,人爲的分層七層。實際上這個七層是不存在的。沒有這七層的概念,只是人爲的劃分而已。區分出來的目的只是讓咱們明白哪一層是幹什麼用的。socket
每一層都運行不一樣的協議。ide
實際上也能夠把它劃成五層、四層。this
七層劃分爲:應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層。
五層劃分爲:應用層、傳輸層、網絡層、數據鏈路層、物理層。
四層劃分爲:應用層、傳輸層、網絡層、網絡接口層。
用戶使用的都是應用程序,均工做於應用層,你們均可以開發本身的應用程序,數據多種多樣,必須規定好數據的組織形式 。
應用層功能:規定應用程序的數據格式。
好比TCP協議能夠爲各類各樣的程序傳遞數據,好比Email、WWW、FTP等。那麼,必須有不一樣協議規定電子郵件、網頁、FTP數據的格式,這些應用程序協議就構成了」應用層」。
表示層的用途是提供一個可供應用層選擇的服務的集合,使得應用層能夠根據這些服務功能解釋數據的含義。表示層如下各層只關心如何可靠地傳輸數據,而表示層關心的是所傳輸數據的表現方式、它的語法和語義。表示服務的例子有統一的數據編碼、數據壓縮格式和加密技術等。
會話層任務是:向兩個實體的表示層提供創建和使用鏈接的方法。將不一樣實體之間的表示層的鏈接稱爲會話。所以會話層的任務就是組織和協調兩個會話進程之間的通訊,並對數據交換進行管理。
傳輸層是通訊子網和資源子網的接口和橋樑,起到承上啓下的做用。
該層的主要任務是:向用戶提供可靠的端到端的差錯和流量控制,保證報文的正確傳輸。傳輸層的做用是向高層屏蔽下層數據通訊的細節,即向用戶透明地傳送報文。
該層常見的協議:TCP/IP中的TCP協議、Novell網絡中的SPX協議和微軟的NetBIOS/NetBEUI協議。
傳輸層提供會話層和網絡層之間的傳輸服務,這種服務從會話層得到數據,並在必要時,對數據進行分割。而後,傳輸層將數據傳遞到網絡層,並確保數據能正確無誤地傳送到網絡層。所以,傳輸層負責提供兩節點之間數據的可靠傳送,當兩節點的聯繫肯定以後,傳輸層則負責監督工做。綜上,傳輸層的主要功能以下:
傳輸鏈接管理:提供創建、維護和拆除傳輸鏈接的功能。傳輸層在網絡層的基礎上爲高層提供面向鏈接和面向無鏈接的兩種服務。
網絡層的做用是在網絡與網絡相互鏈接的環境中,將數據從發送端主機發送到接受端主機。
舉例:
我在學校教室中,我想找隔壁班的妹子,我通知小弟去告訴她,說有個帥哥找你。而小弟就是網關,IP地址就是我所處的教室,MAC地址就是我在教室的某個位置。
早期的時候,數據鏈路層就是來對電信號來作分組的。之前每一個公司都有本身的分組方式,很是的亂,後來造成了統一的標準,即以太網協議Ethernet。
通訊傳輸其實是經過物理的傳輸介質實現的。數據鏈路層的做用就是在這些同構傳輸介質互連的設備之間進行數據處理。
物理層中,將數據的 0 、1轉換爲電壓和脈衝光傳輸給物理的傳輸介質,而相互直連的設備之間使用地址實現傳輸。這種地址被稱爲 MAC 地址,也可稱爲物理地址或硬件地址。採用 MAC 地址信息的首部附加到從網絡層轉發過來的數據上,將其發送到網絡。
網絡層與數據鏈路層都是基於目標地址將數據發送給接收端的,可是網絡層負責將整個數據發送給最終目標地址。而數據鏈路層則只負責發送一個分段內的數據。
OSI七層網絡模型 | TCP/IP四層概念模型 | 對應網絡協議 |
---|---|---|
應用層(Application) | 應用層 | HTTP、TFTP, FTP, NFS, WAIS、SMTP |
表示層(Presentation) | 應用層 | Telnet, Rlogin, SNMP, Gopher |
會話層(Session) | 應用層 | SMTP, DNS |
傳輸層(Transport) | 傳輸層 | TCP, UDP |
網絡層(Network) | 網絡層 | IP, ICMP, ARP, RARP, AKP, UUCP |
數據鏈路層(Data Link) | 數據鏈路層 | FDDI, Ethernet, Arpanet, PDN, SLIP, PPP |
物理層(Physical) | 數據鏈路層 | IEEE 802.1A, IEEE 802.2到IEEE 802.11 |
服務器端先初始化Socket,而後與端口綁定(bind),對端口進行監聽(listen),調用accept開始阻塞,等待客戶端鏈接。在這時若是有個客戶端初始化一個Socket,而後鏈接服務器(connect),若是鏈接成功,這時客戶端與服務器端的鏈接就創建了。客戶端發送數據請求,服務器端接收請求並處理請求,而後把迴應數據發送給客戶端,客戶端讀取數據,最後關閉鏈接,一次交互結束。
經過三次握手創建鏈接,通信完成時要拆除鏈接
第一次握手
:客戶端發送帶有 SYN 標誌的鏈接請求報文段,而後進入 SYN_SEND 狀態,等待服務端確認。第二次握手
:服務端接受到客戶端的 SYN 報文段後,須要發送 ACK 信息對這個 SYN 報文段進行確認。同時,還要發送本身的 SYN 請求信息。服務端會將上述信息放到一個報文段(SYN+ACK 報文段)中,一併發送給客戶端,此時服務端進入 SYN_RECV 狀態。第三次握手
:客戶端接收到服務端的 SYN+ACK 報文段後,會向服務端發送 ACK 確認報文段,這個報文段發送完畢後,客戶端和服務端都進入 ESTABLEISHED 狀態,完成 TCP 三次握手。面向鏈接
的因此只能用於端到端的通信。面向無鏈接
的通信協議。HTTP
、FTP
、SMTP
客戶端代碼:
/** * @author Jack */ public class Client { public static void main(String[] args) throws IOException { Socket socket = new Socket(); // 超時時間 socket.setSoTimeout(3000); // 鏈接本地,端口2000;超時時間3000ms socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), 2000), 3000); System.out.println("已發起服務器鏈接..."); System.out.println("客戶端信息:" + socket.getLocalAddress() + " P:" + socket.getLocalPort()); System.out.println("服務器信息:" + socket.getInetAddress() + " P:" + socket.getPort()); try { // 發送接收數據 todo(socket); } catch (Exception e) { System.out.println("異常關閉"); } // 釋放資源 socket.close(); System.out.println("客戶端已退出~"); } private static void todo(Socket client) throws IOException { // 構建鍵盤輸入流 InputStream in = System.in; BufferedReader input = new BufferedReader(new InputStreamReader(in)); // 獲得Socket輸出流,並轉換爲打印流 OutputStream outputStream = client.getOutputStream(); PrintStream socketPrintStream = new PrintStream(outputStream); // 獲得Socket輸入流,並轉換爲BufferedReader InputStream inputStream = client.getInputStream(); BufferedReader socketBufferedReader = new BufferedReader(new InputStreamReader(inputStream)); boolean flag = true; do { // 鍵盤讀取一行 String str = input.readLine(); // 發送到服務器 socketPrintStream.println(str); // 從服務器讀取一行 String echo = socketBufferedReader.readLine(); if ("bye".equalsIgnoreCase(echo)) { flag = false; } else { System.out.println(echo); } } while (flag); // 資源釋放 socketPrintStream.close(); socketBufferedReader.close(); } }
服務端代碼:
/** * @author jack */ public class Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); System.out.println("服務器準備就緒..."); System.out.println("服務器信息:" + server.getInetAddress() + " P:" + server.getLocalPort()); // 等待客戶端鏈接 for (; ; ) { // 獲得客戶端 Socket client = server.accept(); // 客戶端構建異步線程 ClientHandler clientHandler = new ClientHandler(client); // 啓動線程 clientHandler.start(); } } /** * 客戶端消息處理 */ private static class ClientHandler extends Thread { private Socket socket; private boolean flag = true; ClientHandler(Socket socket) { this.socket = socket; } @Override public void run() { super.run(); System.out.println("新客戶端鏈接:" + socket.getInetAddress() + " P:" + socket.getPort()); try (// 獲得打印流,用於數據輸出;服務器回送數據使用 PrintStream socketOutput = new PrintStream(socket.getOutputStream()); // 獲得輸入流,用於接收數據 BufferedReader socketInput = new BufferedReader(new InputStreamReader( socket.getInputStream()))) { do { // 服務器拿到拿到一條數據 String str = socketInput.readLine(); if ("bye".equalsIgnoreCase(str)) { flag = false; // 回送 socketOutput.println("bye"); } else { // 打印到屏幕。並回送數據長度 System.out.println(str); socketOutput.println("服務器收到了,你發送的長度爲 :" + str.length()); } } while (flag); } catch (Exception e) { System.out.println("鏈接異常斷開"); } finally { // 鏈接關閉 if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } System.out.println("客戶端已退出:" + socket.getInetAddress() + " P:" + socket.getPort()); } } }
運行結果:
網絡設備
的位置。
IPv4
,IPv6
。