目錄
1.什么是網絡編程?
2.基本的通信架構
3.網絡通信三要素
4.UDP通信-快速入門
5.UDP通信-多發多收
6.TCP通信-快速入門?????
7.TCP通信-多發多收? ?
8.TCP通信-同時接收多個客戶端
9.TCP通信-綜合案例
1.什么是網絡編程?
????????網絡編程是可以讓設備中的程序與網絡上其他設備中的程序進行數據交互的技術
2.基本的通信架構
????????CS架構:Client客戶端/Server服務端
????????BS架構:Browser瀏覽器/Server服務端
????????無論是CS架構,還是BS架構的軟件都必須依賴網絡編程
3.網絡通信三要素
????????1.IP地址
????????????????IP(Internet Protocol):全稱”互聯網協議地址”,是分配給上網設備的唯一標識,可以用來定位網絡上的設備。
????????????????IP地址有兩種形式:
????????????????????????IPv4:
????????????????????????????????32位,4個字節
????????????????????????????????點分十進制:?192.168.1.66
????????????????????????IPv6:
????????????????????????????????128位
????????????????????????????????冒分十六進制:?2001:0db8:0000:0023:0008:0800:200c:417a
????????????????IP域名: 網址
????????????????公網IP, 內網IP:
????????????????????????公網IP:是可以連接互聯網的IP地址;內網IP:也叫局域網IP,只能組織機構內部使用。????????????????
? ? ? ? ? ? ? ? ? ? ? ? 內網IP:192.168. 開頭的就是常見的局域網地址,范圍即為192.168.0.0--192.168.255.255,專門為組織機構內部使用。
????????????????特殊IP地址:127.0.0.1、localhost:代表本機IP,只會尋找當前所在的主機。
????????????????IP常用命令:
????????????????????????ipconfig :查看本機IP地址
????????????????????????ping IP地址:檢查網絡是否連通
????????????????Java中IP地址的表示:
????????????????????????InetAddress
???
package com.itheima.day13.teacher.demo02_ip;import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;/*** IP:用于在一個網絡里,找到某個計算機設備。一般使用IPv4,比如:192.168.29.33* 域名:因為IP比較難記,所以有了域名系統,更方便記憶* IP和域名的關系,類似于 手機通訊錄里 手機號和姓名備注的關系* 百度的ip:110.242.68.4* 百度的域名:www.baidu.com* IP地址對象:InetAddress**/
public class DemoInetAddress {public static void main(String[] args) throws IOException {//獲取本機ip信息InetAddress local = InetAddress.getLocalHost();String localIp = local.getHostAddress();System.out.println("本機ip = " + localIp);String localName = local.getHostName();System.out.println("本機名 = " + localName);//獲取指定ip或指定域名的信息// InetAddress baidu = InetAddress.getByName("www.baidu.com");InetAddress baidu = InetAddress.getByName("110.242.68.4");String baiduName = baidu.getHostName();System.out.println("baiduName = " + baiduName);String baiduIp = baidu.getHostAddress();System.out.println("baiduIp = " + baiduIp);//測試指定域名的網絡是否暢通:200ms之內能否ping通百度boolean reachable = baidu.isReachable(200);System.out.println("reachable = " + reachable);}
}
????????2.端口號
????????????????標記正在計算機設備上運行的應用程序的,被規定為一個 16 位的二進制,范圍是 0~65535
????????????????分類:
????????????????????????周知端口:0~1023,被預先定義的知名應用占用(如:HTTP占用 80,FTP占用21) ????????????????
????????????????????????注冊端口:1024~49151,分配給用戶進程或某些應用程序
????????????????????????動態端口:49152到65535,之所以稱為動態端口,是因為它 一般不固定分配某種進程,而是動態分配
????????????????注意:我們自己開發的程序一般選擇使用注冊端口,且一個設備中不能出現兩個程序的端口號一樣,否則出錯。
? ? ? ? 3.協議
? ? ? ? ? ? ? ? 1.網絡上通信的設備,事先規定的連接規則,以及傳輸數據的規則被稱為網絡通信協議。
? ? ? ? ? ? ? ? 2.開放式網絡互聯標準
????????????????????????OSI網絡參考模型:全球網絡互聯標準
????????????????????????TCP/IP網絡模型:事實上的國際標準
?????????????????
? ? ? ? ? ? ? ? 3.傳輸層的2個通信協議???????
????????????????????????UDP:用戶數據報協議
????????????????????????特點:
????????????????????????????????無連接、不可靠通信,通信效率高
????????????????????????????????不事先建立連接,數據按照包發,一包數據包含:自己的IP、程序端口,目的地IP、程序端口和數據(限制在64KB內)等。
????????????????????????????????發送方不管對方是否在線,數據在中間丟失也不管,如果接收方收到數據也不返回確認,故是不可靠的 。
????????????????????????應用場景:語音通話、視頻直播
????????????????????????TCP:傳輸控制協議?
????????????????????????特點:
????????????????????????????????面向連接、可靠通信
????????????????????????????????要保證在不可靠的信道上實現可靠的傳輸
????????????????????????TCP主要有三個步驟實現可靠傳輸:
????????????????????????????????三次握手建立可靠連接:目的確定通信雙方,收發消息都是正常無問題的!(全雙工)
????????????????????????????????傳輸數據進行確認:目的保證傳輸數據的可靠性
????????????????????????????????四次揮手斷開連接:目的確保雙方數據的收發都已經完成!
????????????????????????應用場景:網頁、文件下載、支付
4.UDP通信-快速入門
????????Java提供了一個java.net.DatagramSocket類來實現UDP通信。
????????構造器、方法:
?????????
????????客戶端實現步驟:
????????????????創建DatagramSocket對象(客戶端對象)?????
????????????????創建DatagramPacket對象封裝需要發送的數據(數據包對象)
????????????????使用DatagramSocket對象的send方法,傳入DatagramPacket對象
????????????????釋放資源
????????服務端實現步驟???
????????????????創建DatagramSocket對象并指定端口(服務端對象)
????????????????創建DatagramPacket對象接收數據(數據包對象)
????????????????使用DatagramSocket對象的receive方法,傳入DatagramPacket對象
????????????????釋放資源
package com.itheima.day13.teacher.demo01_udp;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;/***/
public class Sender {public static void main(String[] args) throws Exception {//1. 創建DatagramSocket對象:因為它提供了收發udp數據包的方法DatagramSocket ds = new DatagramSocket();//2. 準備數據包byte[] data = "hello".getBytes();DatagramPacket packet =new DatagramPacket(data, data.length, InetAddress.getLocalHost(), 7788);//3. 把數據包里的數據發送出去ds.send(packet);//4. 釋放資源ds.close();}
}----------------
package com.itheima.day13.teacher.demo01_udp;import java.net.DatagramPacket;
import java.net.DatagramSocket;/***/
public class Receiver {public static void main(String[] args) throws Exception {//1. 創建DatagramSocket對象,并監聽7788端口DatagramSocket ds = new DatagramSocket(7788);//2. 準備數據包。用于存儲 接收到的數據。UDP的數據包64Kbyte[] buffer = new byte[1024 * 64];DatagramPacket packet = new DatagramPacket(buffer, buffer.length);//3. 接收數據。接收到的數據會被放到packet對象里ds.receive(packet);//4. 把接收到的數據打印出來String str =new String(packet.getData(), packet.getOffset(), packet.getLength());System.out.println("str = " + str);//5. 釋放資源ds.close();}
}
????????
5.UDP通信-多發多收
????????客戶端實現步驟:
????????????????創建DatagramSocket對象(發送端對象)
????????????????使用while死循環不斷的接收用戶的數據輸入,如果用戶輸入的exit則退出程序
????????????????如果用戶輸入的不是exit, 把數據封裝成DatagramPacket
????????????????使用DatagramSocket對象的send方法將數據包對象進行發送
????????????????釋放資源
????????服務端實現步驟:
????????????????創建DatagramSocket對象并指定端口(接收端對象)
????????????????創建DatagramPacket對象接收數據(數據包對象)
????????????????使用DatagramSocket對象的receive方法傳入DatagramPacket對象
????????????????使用while死循環不斷的進行第3步
????????
package com.itheima.day13.teacher.demo03_udp;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;/*** 1. 發送的消息內容,由用戶進行輸入:用Scanner* Scanner scanner = new Scanner(System.in);* String line = scanner.nextLine();* 2. 可以多次發送消息,進行持續通信* 發送者持續多次發送* 如果用戶輸入的是“byebye”,就結束循環*/
public class Sender {public static void main(String[] args) throws Exception {//1. 創建DatagramSocket對象:因為它提供了收發udp數據包的方法DatagramSocket ds = new DatagramSocket();//2. 準備一個掃描器,用于讀取用戶的輸入Scanner scanner = new Scanner(System.in);//3. 持續通信:不斷讀取用戶的輸入,把內容發送出去while (true) {//讀取用戶輸入的內容String line = scanner.nextLine();//封裝到數據包里byte[] data = line.getBytes();DatagramPacket packet =new DatagramPacket(data, data.length, InetAddress.getLocalHost(), 7788);//把數據包里的數據發送出去ds.send(packet);//如果用戶輸入的是byebye,就結束循環if ("byebye".equals(line)) {break;}}//4. 釋放資源ds.close();}
}---------------------
package com.itheima.day13.teacher.demo03_udp;import java.net.DatagramPacket;
import java.net.DatagramSocket;/*** @author liuyp* @since 2024/02/28*/
public class Receiver {public static void main(String[] args) throws Exception {//1. 創建DatagramSocket對象,并監聽7788端口DatagramSocket ds = new DatagramSocket(7788);//2. 準備數據包。用于存儲 接收到的數據。UDP的數據包64Kbyte[] buffer = new byte[1024 * 64];DatagramPacket packet = new DatagramPacket(buffer, buffer.length);//3. 持續通信:不斷的接收數據并打印出來while (true) {//4. 接收數據。接收到的數據會被放到packet對象里ds.receive(packet);//5. 把接收到的數據打印出來String str =new String(packet.getData(), packet.getOffset(), packet.getLength());System.out.println(packet.getSocketAddress() +"發送了: " + str);}//5. 釋放資源// ds.close();}
}
6.TCP通信-快速入門?????
???? ? ?1.Java提供了一個java.net.Socket類來實現TCP通信。
????????? ? ? ? 2.客戶端實現步驟
????????????????創建客戶端的Socket對象,請求與服務端的連接。???????????
????????????????使用socket對象調用getOutputStream()方法得到字節輸出流。
? ? ? ? ? ? ? ? 使用字節輸出流完成數據的發送。
????????????????釋放資源:關閉socket管道。
? ? ? ? 3.服務端實現步驟
????????????????創建ServerSocket對象,注冊服務端端口。
????????????????調用ServerSocket對象的accept()方法,等待客戶端的連接,并得到Socket管道對象。
????????????????通過Socket對象調用getInputStream()方法得到字節輸入流、完成數據的接收。
????????????????釋放資源:關閉socket管道
package com.itheima.day13.teacher.demo04_tcp;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;/***/
public class Client{public static void main(String[] args) throws IOException {//1. 使用TCP連接 本機的8888端口:創建Socket對象Socket socket = new Socket("127.0.0.1", 8888);//2. 通過Socket,把數據發出去到服務端DataOutputStream dos = new DataOutputStream(socket.getOutputStream());dos.writeUTF("hello");//3. 通過Socket,接收服務端返回的數據DataInputStream dis = new DataInputStream(socket.getInputStream());String answer = dis.readUTF();System.out.println("收到服務端返回結果:" + answer);//4. 釋放資源dis.close();dos.close();socket.close();}
}----------------------
package com.itheima.day13.teacher.demo04_tcp;import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;/*** @author liuyp* @since 2024/02/28*/
public class Server {public static void main(String[] args) throws IOException {//1. 監聽8888端口:創建ServerSocketServerSocket serverSocket = new ServerSocket(8888);//2. 獲取客戶端的連接:Socket對象。是阻塞方法。如果沒有客戶端連接進來,就一直阻塞等待Socket socket = serverSocket.accept();//3. 通過Socket,接收客戶端發過來的數據DataInputStream dis = new DataInputStream(socket.getInputStream());String data = dis.readUTF();System.out.println("接收到客戶端發來的數據:" + data);//4. 通過Socket,給客戶端返回數據DataOutputStream dos = new DataOutputStream(socket.getOutputStream());dos.writeUTF("hi");//5. 釋放資源dos.close();dis.close();socket.close();serverSocket.close();}
}
7.TCP通信-多發多收? ?
????????客戶端使用死循環,讓用戶不斷輸入消息。
????????服務端也使用死循環,控制服務端收完消息,繼續等待接收下一個消息。
package com.itheima.day13.teacher.demo05_tcp;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;/*** 1. 客戶端給服務端發送的內容:由用戶輸入* 2. 實現客戶端和服務端的持續通信*/
public class Client{public static void main(String[] args) throws IOException {//1. 使用TCP連接 本機的8888端口:創建Socket對象Socket socket = new Socket("127.0.0.1", 8888);Scanner scanner = new Scanner(System.in);DataOutputStream dos = new DataOutputStream(socket.getOutputStream());DataInputStream dis = new DataInputStream(socket.getInputStream());while (true) {//2. 通過Socket,把數據發出去到服務端:使用Scanner讀取用戶輸入的內容,把內容發出去String line = scanner.nextLine();dos.writeUTF(line);//3. 通過Socket,接收服務端返回的數據String answer = dis.readUTF();System.out.println("收到服務端返回結果:" + answer);//如果用戶輸入的內容是byebye,就結束if ("byebye".equals(line)) {break;}}//4. 釋放資源dis.close();dos.close();socket.close();}
}-----------------
package com.itheima.day13.teacher.demo05_tcp;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;/*** @author liuyp* @since 2024/02/28*/
public class Server {public static void main(String[] args) throws IOException {//1. 監聽8888端口:創建ServerSocketServerSocket serverSocket = new ServerSocket(8888);//2. 獲取客戶端的連接:Socket對象。是阻塞方法。如果沒有客戶端連接進來,就一直阻塞等待Socket socket = serverSocket.accept();DataInputStream dis = new DataInputStream(socket.getInputStream());DataOutputStream dos = new DataOutputStream(socket.getOutputStream());while (true) {//3. 通過Socket,接收客戶端發過來的數據String data = dis.readUTF();System.out.println("接收到客戶端發來的數據:" + data);//4. 通過Socket,給客戶端返回數據dos.writeUTF("hi");if ("byebye".equals(data)) {break;}}//5. 釋放資源dos.close();dis.close();socket.close();serverSocket.close();}
}
8.TCP通信-同時接收多個客戶端
????????主線程定義了循環負責接收客戶端Socket管道連接?
????????每接收到一個Socket通信管道后分配一個獨立的線程負責處理它。
package com.itheima.day13.teacher.demo06_tcp;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;/***/
public class ServerWorkerRunnable implements Runnable{private Socket socket;public ServerWorkerRunnable(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {DataInputStream dis = new DataInputStream(socket.getInputStream());DataOutputStream dos = new DataOutputStream(socket.getOutputStream());while (true) {//通過Socket,接收客戶端發過來的數據。也是阻塞方法,即:如果當前socket里沒有數據可讀取,就阻塞String data = dis.readUTF();System.out.println("接收到客戶端發來的數據:" + data);//通過Socket,給客戶端返回數據dos.writeUTF("hi");if ("byebye".equals(data)) {break;}}//釋放資源dos.close();dis.close();socket.close();} catch (IOException e) {System.out.println("連接已斷開");}}
}--------------------
package com.itheima.day13.teacher.demo06_tcp;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;/***/
public class Server {public static void main(String[] args) throws IOException {//1. 監聽8888端口:創建ServerSocketServerSocket serverSocket = new ServerSocket(8888);//2. 死循環:不斷嘗試接受客戶端的連接。有幾個客戶端連接進來,就接受幾個連接while (true) {//3. 獲取客戶端的連接:Socket對象。是阻塞方法。如果沒有客戶端連接進來,就一直阻塞等待Socket socket = serverSocket.accept();//4. 創建一個線程,由這個新線程專門負責它的通信。線程本身是異步的new Thread(new ServerWorkerRunnable(socket)).start();}// serverSocket.close();}
}----------------
package com.itheima.day13.teacher.demo06_tcp;import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;/*** 1. 客戶端給服務端發送的內容:由用戶輸入* 2. 實現客戶端和服務端的持續通信*/
public class Client{public static void main(String[] args) throws IOException {//1. 使用TCP連接 本機的8888端口:創建Socket對象Socket socket = new Socket("127.0.0.1", 8888);Scanner scanner = new Scanner(System.in);DataOutputStream dos = new DataOutputStream(socket.getOutputStream());DataInputStream dis = new DataInputStream(socket.getInputStream());while (true) {//2. 通過Socket,把數據發出去到服務端:使用Scanner讀取用戶輸入的內容,把內容發出去String line = scanner.nextLine();dos.writeUTF(line);//3. 通過Socket,接收服務端返回的數據String answer = dis.readUTF();System.out.println("收到服務端返回結果:" + answer);//如果用戶輸入的內容是byebye,就結束if ("byebye".equals(line)) {break;}}//4. 釋放資源dis.close();dos.close();socket.close();}
}
9.TCP通信-綜合案例
? ? ? ? 1.即時通信-群聊
????????????????是指一個客戶端把消息發出去,其他在線的全部客戶端都可以收到消息。
????????????????需要用到端口轉發的設計思想。
????????????????????????服務端需要把在線的Socket管道存儲起來,一旦收到一個消息要推送給其他管道。
? ? ? ? 2.實現一個簡易版的BS架構?
????????????????BS架構的基本原理
????????
package com.itheima.day13.teacher.demo07_tcp_tomcat;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;/***/
public class TomcatWorkerRunnable implements Runnable {private Socket socket;public TomcatWorkerRunnable(Socket socket) {this.socket = socket;}@Overridepublic void run() {// while (true) {try {//如果想要接收客戶端提交過來的數據// InputStream is = socket.getInputStream();// is.read();//直接給客戶端返回結果OutputStream os = socket.getOutputStream();os.write("HTTP/1.1 200\r\n".getBytes());os.write("Content-Type: text/html;charset=UTF-8\r\n".getBytes());os.write("\r\n".getBytes());os.write("<h1>Hello World!!!</h1>".getBytes());os.write("<a href='http://www.baidu.com'>百度</a>".getBytes());//必須給瀏覽器返回一個結束標志,否則瀏覽器會一直轉圈socket.shutdownOutput();} catch (IOException e) {System.out.println("斷開連接");}// }}
}----------------------
package com.itheima.day13.teacher.demo07_tcp_tomcat;import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;/***/
public class TomcatServer {public static void main(String[] args) throws IOException {//1. 監聽8080端口。瀏覽器訪問地址的格式 http://ip地址:8080ServerSocket serverSocket = new ServerSocket(8080);//2. 死循環while (true) {//3. 不斷嘗試接受客戶端的連接,得到SocketSocket socket = serverSocket.accept();//4. 把socket交給一個新線程進行處理new Thread(new TomcatWorkerRunnable(socket)).start();}}
}
? ? ? ??
????????