1. 概述
計算機網絡:計算機網絡是指將地理位置不同的具有獨立功能的多臺計算機及其外部設備,通過通信線路連接起來,在網絡操作系統,網絡管理軟件及網絡通信協議的管理和協調下,實現資源共享和信息傳遞的計算機系統。
網絡編程的目的:
無線電臺…傳播交流信息,數據交換。通信想要達到這個效果需要什麼:
1.如何準確的定位網絡上的一臺主機 192.168.16.124:端口, 定位到這個計算機上的某個資源
2.找到了這個主機,如何傳輸數據呢?
2. 網絡通信的要素
(1)如何實現網絡的通信?
通信雙方地址:
ip
端口號
192.168.16,124:5900
(2)網絡編程中的要素:
IP 和 端口號 IP.
網絡通信協議 udp,tcp
3.IP
ip地址:InetAddress
唯一定位一臺網絡上計算機
127.0.0.1 : 本地主機 localhost
ip地址的分類:
ipv4 / ipv6
IPV4 127.0.0.1 , 4個字節組成。, 0~255, 42億~ ; 30億都在北美,亞洲4億。2011年就用盡;
IPV6 :128位。8個無符號整數!
2001:0bb2:aaaa:0015:0000:0000:1aaa:1312!
公網(互聯網)- 私網(局域網)
ABCD類地址192.168.xx.xx,專門給組織內部使用的
域名:記憶IP問題!
IP: www.vip.com
public class TestInetAddress {
public static void main(String[] args) {
/**
* IP Address
*/
try {
//查詢本機地址
InetAddress byName = InetAddress.getByName("127.0.0.1");
System.out.println(byName);// /127.0.0.1
InetAddress localhost = InetAddress.getByName("localhost");
System.out.println(localhost);// localhost/127.0.0.1
InetAddress host = InetAddress.getLocalHost();// 獲得本機IPv4地址 .getLocalHost();
System.out.println(host);// xx/10.0.4.84
//查看網站IP地址
InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress);
//常用方法
System.out.println(inetAddress.getCanonicalHostName());//規範名字 獲得本機IPv4地址
System.out.println(inetAddress.getHostAddress());//獲得本機IPv4地址
System.out.println(inetAddress.getHostName());//域名,或者自己電腦的名字
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
4.端口
端口表示計算機上的一個程序的進程;
不同的進程有不同的端口號!用來區分軟件!被規定 0~65535
TCP,UDP : 65535 * 2 tcp:80,udp:80嗎,單個協議下,端口號不能衝突
端口分類
公有端口 0~1023
HTTP : 80
HTTPS : 443
FTP : 21
Telent : 23
程序註冊端口:1024~49151, 分配用戶或者程序
Tomcat : 8080
MySQL : 3306
Oracle :1521
動態、私有:49152~ 65535
public class TestInetSocketAddress {
public static void main(String[] args) {
/**
* 端口 port
*/
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
System.out.println(socketAddress);
System.out.println(socketAddress.getAddress());
System.out.println(socketAddress.getHostName());//地址
System.out.println(socketAddress.getPort());//端口
InetSocketAddress socketAddress2 = new InetSocketAddress("localhost", 8080);
System.out.println(socketAddress2);
}
}
5.通信協議
網絡通信協議: 速率,傳輸碼率,代碼結構,傳輸控制……
問題:非常的複雜?
大事化小: 分層!
TCP/IP協議簇:實際上是一組協議
重要:
TCP : 用戶傳輸協議
UDP : 用戶數據報協議
出名的協議:TCP:
IP : 網絡互連協議
6.TCP與UDP對比
相同點:
UDP協議和TCP協議都是傳輸層協議。
TCP(Transmission Control Protocol,傳輸控制協議)提供的是面向連接,可靠的字節流服務。即客戶和服務器交換數據前,必須現在雙方之間建立一個TCP連接,之後才能傳輸數據。並且提供超時重發,丟棄重複數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另一端。
UDP(User Data Protocol,用戶數據報協議)是一個簡單的面向數據報的運輸層協議。它不提供可靠性,只是把應用程序傳給IP層的數據報發送出去,但是不能保證它們能到達目的地。由於UDP在傳輸數據報前不用再客戶和服務器之間建立一個連接,且沒有超時重發等機制,所以傳輸速度很快。
TCP三次握手過程
1.主機A通過向主機B 發送一個含有同步序列號標誌位的數據段(SYN)給主機B ,向主機B 請求建立連接,通過這個數據段,主機A告訴主機B 兩件事:我想要和你通信;你可以用哪個序列號作爲起始數據段來回應我。
2.主機B 收到主機A的請求後,用一個帶有確認應答(ACK)和同步序列號(SYN)標誌位的數據段響應主機A,也告訴主機A兩件事:我已經收到你的請求了,你可以傳輸數據了;你要用哪個序列號作爲起始數據段來回應我。
3.主機A收到這個數據段後,再發送一個確認應答,確認已收到主機B 的數據段:“我已收到回覆,我現在要開始傳輸實際數據了”
TCP四次揮手過程
1.當主機A完成數據傳輸後,將控制位FIN置1,提出停止TCP連接的請求。
2.主機B收到FIN後對其作出響應,確認這一方向上的TCP連接將關閉,將ACK置1。
3.由B 端再提出反方向的關閉請求,將FIN置1。
4.主機A對主機B的請求進行確認,將ACK置1,雙方向的關閉結束。
7.TCP概述
TCP(Transmission Control Protocol 傳輸控制協議)是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,由IETF的RFC 793定義。在簡化的計算機網絡OSI模型中,它完成第四層傳輸層所指定的功能,用戶數據報協議(UDP)是同一層內另一個重要的傳輸協議。在因特網協議族(Internet protocol suite)中,TCP層是位於IP層之上,應用層之下的中間層。不同主機的應用層之間經常需要可靠的像管道一樣的連接,但是IP層不提供這樣的流機制,而是提供不可靠的包交換。
傳輸消息
客戶端
連接服務器
Socket發送消息
客戶端
public class TcpClientDemo01 {
public static void main(String[] args) {
/**
* 客戶端
*/
Socket socket = null;
OutputStream os = null;
try {
//1. 要知道服務器的地址,端口號
InetAddress serverIP = InetAddress.getByName("127.0.0.1");
int port = 9999;
//2. 創建一個socket連接
socket = new Socket(serverIP, port);
//3. 發送消息 IO流
os = socket.getOutputStream();
os.write("你好,歡迎學習狂神說Java" .getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
服務器
建立服務的端口
ServerSocket等待用戶的鏈接
accept接收用的消息
服務端
public class TcpServerDemo01 {
public static void main(String[] args) {
/**
* 服務端
*/
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
//1. 我得有一個地址
serverSocket = new ServerSocket(9999);
while (true) {
//2. 等待客戶端連接過來
socket = serverSocket.accept();
//3. 讀取客戶端的消息
is = socket.getInputStream();
//管道流
baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
System.out.println(baos.toString());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//關閉資源
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件上傳
服務器端
public class TcpServerDemo02 {
public static void main(String[] args) throws IOException {
/**
*服務器端
*/
//1. 創建服務
ServerSocket serverSocket = new ServerSocket(9000);
//2. 監聽客戶端的連接
Socket socket = serverSocket.accept(); //阻塞式監聽,會一直等待客戶端連接
//3. 獲取輸入流
InputStream is = socket.getInputStream();
//4. 文件輸出
FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
//通知客戶端我接收完畢了
OutputStream os = socket.getOutputStream();
os.write("我接受完畢了,你可以斷開了" .getBytes());
//關閉資源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
客戶端
public class TcpClientDemo02 {
public static void main(String[] args) throws IOException {
/**
* 客戶端
*/
//1.創建一個Socket連接
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//2、 創建一個輸出流
OutputStream os = socket.getOutputStream();
//3. 讀取文件
FileInputStream fis = new FileInputStream(new File("qinjiang.jpg"));
//4. 寫出文件
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
//通知服務器,我已經結束了
socket.shutdownOutput(); //我已經傳輸完了!
//確定服務器接收完畢,才能夠斷開連接
InputStream inputStream = socket.getInputStream();
//String byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer2 = new byte[2014];
int len2;
while ((len2 = inputStream.read(buffer2)) != -1) {
baos.write(buffer2, 0, len2);
}
System.out.println(baos.toString());
//5.關閉資源
baos.close();
inputStream.close();
fis.close();
os.close();
socket.close();
}
}
8.UDP概述
UDP(User Data Protocol,用戶數據報協議)UDP在IP報文的協議號是17。 UDP協議全稱是用戶數據報協議,在網絡中它與TCP協議一樣用於處理數據包,是一種無連接的協議。在OSI模型中,在第四層–傳輸層,處於IP協議的上一層。UDP有不提供數據包分組、組裝和不能對數據包進行排序的缺點,也就是說,當報文發送之後,是無法得知其是否安全完整到達的。UDP協議的主要作用是將網絡數據流量壓縮成數據包的形式。一個典型的數據包就是一個二進制數據的傳輸單位。每一個數據包的前8個字節用來包含報頭信息,剩餘字節則用來包含具體的傳輸數據。
功能
爲了在給定的主機上能識別多個目的地址,同時允許多個應用程序在同一臺主機上工作並能獨立地進行數據包的發送和接收,設計用戶數據報協議UDP。使用UDP協議包括:TFTP、SNMP、NFS、DNS、BOOTPUDP使用底層的互聯網協議來傳送報文,同IP一樣提供不可靠的無連接數據包傳輸服務。它不提供報文到達確認、排序、及流量控制等功能。
發送消息
public class UdpClientDemo01 {
public static void main(String[] args) throws IOException {
//1. 建立一個Socket
DatagramSocket socket = new DatagramSocket();
//2. 建個包
String msg = "你好啊,服務器!";
InetAddress localhost = InetAddress.getByName("localhost");
int port = 9090;
// 數據,數據的長度起始,要發送給誰
DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
//3. 發送包
socket.send(packet);
//4. 關閉流
socket.close();
}
}
接收端
public class UdpServerDemo01 {
public static void main(String[] args) throws IOException {
//開放端口
DatagramSocket socket = new DatagramSocket(9090);
// 接收數據包
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet); //阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(), 0, packet.getLength()));
//關閉連接
socket.close();
}
}
9.諮詢
public class UdpSenderDemo01 {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(8888);
//準備數據: 控制檯讀取 System.in
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas, 0, datas.length, new InetSocketAddress("localhost", 6666));
socket.send(packet);
if (data.equals("bye")) {
break;
}
}
//關閉資源
socket.close();
}
}
public class UdpReceiveDemo01 {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(6666);
while (true) {
//準備接收包裹
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet); //阻塞式接收包裹
//斷開連接 bye
byte[] data = packet.getData();
String receiveData = new String(data, 0, data.length);
System.out.println(receiveData);
if (receiveData.equals("bye")) {
break;
}
}
//釋放資源
socket.close();
}
}
10.URL概述
統一資源定位符 (Uniform Resource Locator,URL)URL 是對可以從因特網上得到的資源的位置和訪問方法的一種簡潔的表示。URL 給資源的位置提供一種抽象的識別方法,並用這種方法給資源定位。統一資源定位符只要能夠對資源定位,系統就可以對資源進行各種操作,如存取、更新、替換和查找其屬性。URL 相當於一個文件名在網絡範圍的擴展。因此 URL 是與因特網相連的機器上的任何可訪問對象的一個指針。
測試代碼
public class URLDemo01 {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=kuangshen&password=123");
System.out.println(url.getProtocol()); //協議
System.out.println(url.getHost()); //主機ip
System.out.println(url.getPort()); //端口
System.out.println(url.getPath()); //文件
System.out.println(url.getFile()); //全路徑
System.out.println(url.getQuery()); //參數
}
}
下載資源
public class UrlDown {
public static void main(String[] args) throws IOException {
//1. 下載地址
URL url = new URL("https://m10.music.126.net/20191201174818/c09b1932384617e535421702c26ccc5c/yyaac/0708/0652/0508/0b9b6827b718aa223af92bd52aa2424f.m4a");
//2. 連接到這個資源 HTTP
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fos = new FileOutputStream("f.m4a");
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
fos.write(buffer, 0, len); //寫出這個數據
}
fos.close();
inputStream.close();
urlConnection.disconnect(); //斷開連接
}
}