【JavaSE筆記】網絡基礎&網絡編程

本期知識點:
網絡基礎
網絡編程

一. 網絡基礎

1.網絡模型概述:

計算機網絡之間以何種規則進行通信,就是網絡模型研究問題。
網絡模型一般是指
OSI(Open System Interconnection開放系統互連)七層參考模型
TCP/IP四層參考模型

主機至網絡層(物理層 , 數據鏈路層) , 網際層 , 傳輸層 , 應用層(應用層 , 表示層 , 會話層)

2.網絡模型7層概述:

a. 物理層:

主要定義物理設備標準,如網線的接口類型、光纖的接口類型、各種傳輸介質的傳輸速率等。它的主要作用是傳輸比特流(就是由1、0轉化爲電流強弱來進行傳輸,到達目的地後在轉化爲1、0)。這一層的數據叫做比特。

b. 數據鏈路層:

主要將從物理層接收的數據進行MAC地址(網卡的地址)的封裝與解封裝。常把這一層的數據叫做幀。在這一層工作的設備是交換機,數據通過交換機來傳輸。 

c. 網絡層:

主要將從下層接收到的數據進行IP地址(例192.168.0.1)的封裝與解封裝。在這一層工作的設備是路由器,常把這一層的數據叫做數據包。 

d. 傳輸層:

定義了一些傳輸數據的協議和端口號(WWW端口80等),如:TCP(傳輸控制協議,傳輸效率低,可靠性強,用於傳輸可靠性要求高,數據量大的數據),UDP(用戶數據報協議,與TCP特性恰恰相反,用於傳輸可靠性要求不高,數據量小的數據,如QQ聊天數據就是通過這種方式傳輸的)。主要是將從下層接收的數據進行分段和傳輸,到達目的地址後再進行重組。常常把這一層數據叫做段。 

e.會話層:

通過傳輸層(端口號:傳輸端口與接收端口)建立數據傳輸的通路。主要在你的系統之間發起會話或者接受會話請求(設備之間需要互相認識可以是IP也可以是MAC或者是主機名) 

f.表示層:

主要是進行對接收的數據進行解釋、加密與解密、壓縮與解壓縮等(也就是把計算機能夠識別的東西轉換成人能夠能識別的東西(如圖片、聲音等)。 

g.應用層: 

主要是一些終端的應用,比如說FTP(各種文件下載),WEB(IE瀏覽),QQ之類的(可以把它理解成我們在電腦屏幕上可以看到的東西.就是終端應用)。

3.網絡編程的三要素:

ip
端口號
協議

a.IP:

1)IP概述:

所謂IP地址就是給每個連接在Internet上的主機分配的一個32bit地址。 

2)IP的組成:

IP地址 = 網絡地址+主機地址
A類IP地址:第一段號碼爲網絡地址,剩下的三段號碼爲本地計算機的號碼
B類IP地址:前二段號碼爲網絡地址,剩下的二段號碼爲本地計算機的號碼
C類IP地址:前三段號碼爲網絡地址,剩下的一段號碼爲本地計算機的號碼

3)IP地址分類:

A類1.0.0.1---127.255.255.254
(1)10.X.X.X是私有地址(私有地址就是在互聯網上不使用,而被用在局域網絡中的地址)
(2)127.X.X.X是保留地址,用做循環測試用的。

B類128.0.0.1---191.255.255.254

注:172.16.0.0---172.31.255.255是私有地址。

C類192.0.0.1---223.255.255.254

注:192.168.X.X是私有地址

D類224.0.0.1---239.255.255.254
E類240.0.0.1---247.255.255.254

4)特殊地址:

127.0.0.1 迴環地址,可用於測試本機的網絡是否有問題.ping 127.0.0.1  
DOS命令 ipconfig:查看本機IP地址
xxx.xxx.xxx.255 廣播地址

b.端口號:

物理端口:

物理設備對應的端口, 網卡口

邏輯端口:

用來標示我們的計算機上的進程(正在運行的程序) , 端口號的有效範圍應該是0-65535,其中0-1024被系統佔用或者保留

c.協議(UDP和TCP的區別):

UDP
把數據打成一個數據包 , 不需要建立連接
數據包的大小有限制不能超過64k
因爲無連接,所以屬於不可靠協議(可能丟失數據)
因爲無連接 ,所以效率高
TCP
需要建立連接,形成連接通道
數據可以使用連接通道直接進行傳輸,無大小限制
因爲有鏈接,所以屬於可靠協議

二. 網絡編程

1.InetAddress類

a.概述

public class InetAddress extends Objectimplements Serializable
此類表示互聯網協議 (IP) 地址。
此類沒有構造方法,但是有靜態成員方法。

b.常用的方法

public static InetAddress getByName(String host) throws UnknownHostException
在給定主機名的情況下確定主機的 IP 地址。主機名可以是機器名,也可以是其 IP 地址的文本表示形式。
public String getHostAddress() 返回IP地址字符串
public String getHostName() 返回此IP地址的主機名
import java.io.IOException;
import java.net.InetAddress;
public class ipDemo {
public static void main(String[] args) throws IOException {
InetAddress address = InetAddress.getByName("192.168.100.2");
}
System.out.println(address.getHostName());//YangFan (我的電腦的名字)
}

2.Socket通信原理

a.類 Socket

i.概述

public class Socket extends Object
此類實現客戶端套接字(也可以就叫“套接字”)。套接字是臺機器間通信的端點。
Socket=IP+端口號

ii.常用方法

public void close()throws IOException 關閉此套接字。 
public InetAddress getInetAddress()返回套接字連接的地址。 
public InputStream getInputStream() throws IOException 返回此套接字的輸入流。
public OutputStream getOutputStream() throws IOException 返回此套接字的輸出流。 
public void shutdownInput() throws IOException   此套接字的輸入流置於“流的末尾”。
發送到套接字的輸入流端的任何數據都將被確認然後被靜默丟棄。 
public void shutdownOutput() throws IOException   禁用此套接字的輸出流。
對於 TCP 套接字,任何以前寫入的數據都將被髮送,並且後跟 TCP 的正常連接終止序列。 如果在套接字上調用 shutdownOutput() 後寫入套接字輸出流,則該流將拋出 IOException。

b.Socket原理機制:

通信的兩端都有Socket。

網絡通信其實就是Socket間的通信。

數據在兩個Socket間通過IO傳輸。

3.UDP協議發送/接收數據

a.類 DatagramSocket

i.概述

public class DatagramSocket extends Object
此類表示用來發送和接收數據報包的套接字。
數據報套接字是包投遞服務的發送或接收點。
每個在數據報套接字上發送或接收的包都是單獨編址和路由的。
從一臺機器發送到另一臺機器的多個包可能選擇不同的路由,也可能按不同的順序到達。

ii.構造方法

public DatagramSocket(int port, InetAddress laddr) throws SocketException
創建數據報套接字,將其綁定到指定的本地地址。本地端口必須在 0 到 65535 之間(包括兩者)。如果 IP 地址爲 0.0.0.0,套接字將被綁定到通配符地址,IP 地址由內核選擇。
public DatagramSocket()throws SocketException
構造數據報套接字並將其綁定到本地主機上任何可用的端口。套接字將被綁定到通配符地址,IP 地址由內核來選擇。

iii.常用方法

public void send(DatagramPacket p)throws IOException
從此套接字發送數據報包。
DatagramPacket 包含的信息指示:將要發送的數據、其長度、遠程主機的 IP 地址和遠程主機的端口號。 
public void receive(DatagramPacket p)throws IOException
從此套接字接收數據報包。
當此方法返回時,DatagramPacket 的緩衝區填充了接收的數據。數據報包也包含發送方的 IP 地址和發送方機器上的端口號。
public void close()關閉此數據報套接字。

b.類 DatagramPacket

i.概述

public final class DatagramPacket extends Object
此類表示數據報包。 
數據報包用來實現無連接包投遞服務。
每條報文僅根據該包中包含的信息從一臺機器路由到另一臺機器。
從一臺機器發送到另一臺機器的多個包可能選擇不同的路由,也可能按不同的順序到達。不對包投遞做出保證。

ii.構造方法

public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
構造數據報包,用來將長度爲 length 的包發送到指定主機上的指定端口號。
length 參數必須小於等於 buf.length。 

iii.常用方法

public InetAddress getAddress() 返回某臺機器的 IP 地址

此數據報將要發往該機器或者是從該機器接收到的。

public byte[] getData() 返回數據緩衝區。
public int getLength() 返回將要發送或接收到的數據的長度。

c.發送數據

i.步驟:
1)創建UDP通訊客戶端對象(DatagramSocket)
2)創建數據報包對象
3)發送 數據
4)釋放資源

d.接收數據

i.步驟: 
1)創建UDP通訊協議服務器端對象(DatagramSocket) 注意要用有參數構造 指定端口號
2)創建數據報包,作用用來接收數據 
3)接收數據 receive(dp) ;
4)解析數據報包,拿出數據 dp.getData(),dp.getLength() 
5) 釋放資源
UDP多次發送消息:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPServer {
	public static void main(String[] args) throws IOException {
//		創建UDP通訊協議服務器端對象
		DatagramSocket ds = new DatagramSocket(4444);
		System.out.println("服務器已經開啓,等待連接...");
//		創建數據報包,接收數據
		while(true){
			byte[]a=new byte[1024];
			int len = a.length;
			DatagramPacket dp = new DatagramPacket(a, len);
//			接收數據
			ds.receive(dp);
//			解析
			byte[] b = dp.getData(); 
			int len2 = a.length;
			System.out.println(new String(b, 0, len2));
		}
	}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class UDPClient {
	public static void main(String[] args) throws IOException {
		InetAddress address = InetAddress.getByName("192.168.100.2");
		//創建UDP客戶端對象
		DatagramSocket ds = new DatagramSocket();
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String msg=null;
		System.out.println("請輸入消息:");
		while((msg=br.readLine())!=null){
			System.out.println("請輸入消息:");
			byte[] a = msg.getBytes();
			int len = a.length;
			DatagramPacket dp = new DatagramPacket(a,len,address,4444);
			ds.send(dp);
		}
		ds.close();
	}
}
UPD的多線程描述:
import java.io.IOException;
import java.net.DatagramSocket;

public class ThreadDemo {
	public static void main(String[] args) throws IOException{
		DatagramSocket sent = new DatagramSocket();
		DatagramSocket get = new DatagramSocket(4444);
		new GetThread(get).start();
		new SendThread(sent).start();
	}
}
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class GetThread extends Thread {
	private DatagramSocket ds;
	
	public GetThread(DatagramSocket ds) {
		this.ds = ds; 
	}
	@Override
	public void run() {
		try {
			System.out.println("服務器已開啓,等待連接...");
			while(true){
				byte[] by = new byte[1024];
				int length = by.length;
				DatagramPacket dp = new DatagramPacket(by, length);		
				//接收
				ds.receive(dp);
				//解析
				byte[] a = dp.getData();
				int length2 = dp.getLength();
				String ip = dp.getAddress().getHostAddress();
				System.out.println("服務端:"+new String(a, 0, length2));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class SendThread extends Thread {
	
	private DatagramSocket ds;
	public SendThread(DatagramSocket ds) {
		this.ds=ds;
	}
	@Override
	public void run() {
		try {
			InetAddress ia = InetAddress.getByName("192.168.100.2");
			BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
			String msg=null;
			
			while((msg=bfr.readLine())!=null){
				
				byte[] a = msg.getBytes();
				int length = a.length;
				DatagramPacket dp = new DatagramPacket(a, length,ia,4444);
				ds.send(dp);
			}
			ds.close();
			
		
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

4.TCP協議發送/接收數據

a.類 ServerSocket

i.概述

public class ServerSocket extends Object
此類實現服務器套接字。服務器套接字等待請求通過網絡傳入。
用於TCP通訊協議服務器端對象

ii.構造方法 

public ServerSocket(int port)throws IOException 創建綁定到特定端口的服務器套接字。

iii.常用方法

public Socket accept() throws IOException偵聽並接受到此套接字的連接。

此方法在連接傳入之前一直阻塞。

public void close() throws IOException   關閉此套接字。
public InetAddress getInetAddress()返回此服務器套接字的本地地址。

b.發送數據

步驟:
1)創建TCP客戶端的Socket對象
2)獲取輸出流,寫數據
3)寫數據
4)釋放資源

c.接收數據

步驟:
1)創建TCP服務器端的ServerSocket對象
2)監聽客戶端
3)獲取輸入流對象
4)讀取數據
5)釋放資源

d.TCP傳輸容易出現的問題

問題:
客戶端連接上服務端,兩端都在等待,沒有任何數據傳輸。
分析:
因爲read方法或者readLine方法是阻塞式。
解決:

自定義結束標記

使用shutdownInput,shutdownOutput方法。

TCP傳輸數據

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class TCP客戶端 {
	public static void main(String[] args) throws IOException {
		//類 Socket
		Socket s = new Socket("192.168.100.2", 4444);
		//獲取輸出流
		OutputStream os = s.getOutputStream();
		os.write(new Scanner(System.in).nextLine().getBytes());
		
		//讀取服務端反饋回來的信息
		InputStream is = s.getInputStream();
		byte[] a = new byte[1024];
		int len = is.read(a);
		System.out.println(new String(a,0,len));
		s.close();
	}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TCP服務端 {
	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(4444);
		//監聽客戶端
		System.out.println("服務器已開啓,等待連接...");
		Socket sk = ss.accept();
		System.out.println("一個客戶端已經連接");
		//讀取數據
		InputStream is = sk.getInputStream();	
		byte[] by = new byte[1024*8];
		int len = is.read(by);
		System.out.println(new String(by,0,len));
		//反饋
		OutputStream os = sk.getOutputStream();
		os.write("服務端已收到了".getBytes());
		
	}
}

TCP傳輸的包裝

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class TCP服務端 {
	public static void main(String[] args) throws IOException {
		// 創建服務端ServerSocket 套接字
		ServerSocket ss = new ServerSocket(4444);
		// 監聽客戶端
		System.out.println("服務器已經開啓等待連接...");
		Socket accept = ss.accept();
		// 獲取管道中的輸入輸出流
		InputStream is = accept.getInputStream();
		// 包裝管道中的輸入流
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		String msg= null;
		while((msg=br.readLine())!=null){
			System.out.println(msg);
		}
	}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class TCP客戶端 {
	public static void main(String[] args) throws IOException {
		//創建  套接字 對象
		Socket s = new Socket("192.168.0.40", 4444);
		//獲取通道中的輸出流
		OutputStream os = s.getOutputStream();
		//獲取通道中的輸入流
		InputStream is = s.getInputStream();
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		//包裝輸出流
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
		String msg = null;
		while((msg=br.readLine())!=null){
			bw.write(msg);
			bw.newLine();
			bw.flush();
		}
		s.close();
	}
}

TCPC傳輸讀取文件內容

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class TCP_Client {
	public static void main(String[] args) throws IOException {
//	1)創建TCP客戶端的Socket對象
		Socket s = new Socket("192.168.100.2", 3333);
//	2)獲取輸出流,寫數據
		OutputStream os = s.getOutputStream();
		InputStream is = s.getInputStream();
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
		BufferedReader br = new BufferedReader(new FileReader("測試.txt"));
//	3)寫數據
		String msg = null;
		while((msg=br.readLine())!=null){
			bw.write(msg);
			bw.newLine();
			bw.flush();
		}
		s.isOutputShutdown();
//	4)釋放資源
		s.close();
		br.close();
	}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCP_Server {
	public static void main(String[] args) throws IOException {
//		1)創建TCP服務器端的ServerSocket對象
		ServerSocket ss = new ServerSocket(3333);
		System.out.println("服務器已開啓,等待連接...");
//		2)監聽客戶端
		Socket s = ss.accept();
		System.out.println("一個客戶端已經連接");
//		3)獲取輸入流對象
		InputStream is = s.getInputStream();
		OutputStream os = s.getOutputStream();
//		4)讀取數據
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		String msg=null;
		while((msg=br.readLine())!=null){
			System.out.println(msg);
		}
		
	}
}


TCP傳輸文件

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class TCPClient {
	public static void main(String[] args) throws IOException {
		//創建 套接字對象
		Socket s = new Socket("192.168.0.40",4444);
		
		InputStream is = s.getInputStream();
		OutputStream os = s.getOutputStream();
		
		BufferedInputStream bi=new BufferedInputStream(
				new FileInputStream("C:\\Users\\Administrator\\Desktop\\測試.jpg"));
		BufferedOutputStream bo = new BufferedOutputStream(os);
		byte[] a = new byte[1024];
		int length = 0;
		while((length=bi.read(a))!=-1){
			bo.write(a,0,length);
			bo.flush();
		}
		s.shutdownOutput();
		
		// 讀取反饋
		byte[] by = new byte[1024];
		int len = is.read(by);
		System.out.println(new String(by, 0, len));
		
		s.close();
		bi.close();
		bo.close();
	}
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPserver {
	public static void main(String[] args) throws IOException {
		ServerSocket ss=new ServerSocket(4444);
		// 監聽客戶端
		System.out.println("服務器已經開啓等待連接...");
		Socket accept = ss.accept();
		System.out.println("客戶端連接成功");
		// 獲取管道中的輸入輸出流
		InputStream is = accept.getInputStream();
		OutputStream os = accept.getOutputStream();
		// 包裝管道中的輸入流
		BufferedInputStream bi = new BufferedInputStream(is);
		BufferedOutputStream bo = new BufferedOutputStream
				(new FileOutputStream("E:\\new.jpg"));
		
		byte[] a = new byte[1024];
		int length = 0;
		while((length=bi.read(a))!=-1){
			bo.write(a, 0, length);
			bo.flush();
		}
		//給客戶端反饋
		os.write("文件上傳完畢".getBytes());
		
		bi.close();
		bo.close();
	}
}


TCP多線程

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {
	public static void main(String[] args) throws IOException {
//		創建TCP服務器端的ServerSocket對象
		ServerSocket ss = new ServerSocket(6666);
//		監聽客戶端	
		System.out.println("服務器已經開啓,等待連接...");
		int cnt=1;
		while(true){
			Socket accept = ss.accept();//服務器會在這裏等待連接
			System.out.println("第"+cnt+++"個客戶端已建立連接");
			//開啓子線程
			new TCPThread(accept).start();
		}
	}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class TCPThread extends Thread {
	private Socket s ;
	public TCPThread(Socket s ) {
		this.s = s;
	}
	@Override
	public void run() {
		try {
//			獲取輸入輸出流對象
			InputStream is = s.getInputStream();
			OutputStream os = s.getOutputStream();
			//包裝
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			BufferedWriter bw = new BufferedWriter
					(new FileWriter(Thread.currentThread().getName()+"new.txt"));
			
//			讀取數據
			String line =null;
			while((line = br.readLine())!=null){
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
			//給客戶端反饋
			os.write("文件上傳完畢".getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
//客戶端1
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class TCPClient {
	public static void main(String[] args) throws IOException {
//		1)創建TCP客戶端的Socket對象
		Socket s = new Socket("192.168.100.2",6666);
//		2)獲取輸入輸出流,寫數據
		InputStream is = s.getInputStream();
		OutputStream os = s.getOutputStream();
//		//包裝
		BufferedReader br = new BufferedReader(new FileReader("測試.txt"));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
//		3)寫數據
		String line = null;
		while((line=br.readLine())!=null){
			bw.write(line);
			bw.newLine();
			bw.flush();//要刷新!!!
		}
		//停止標誌
		s.shutdownOutput();
		//讀取反饋
		byte []a = new byte[1024];
		int len = is.read(a);
		System.out.println(new String(a, 0, len));
//		4)釋放資源
		s.close();
		
	}
//客戶端2
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class TCPClient2 {
	public static void main(String[] args) throws IOException {
//		1)創建TCP客戶端的Socket對象
		Socket s = new Socket("192.168.100.2",6666);
//		2)獲取輸入輸出流,寫數據
		InputStream is = s.getInputStream();
		OutputStream os = s.getOutputStream();
//		//包裝
		BufferedReader br = new BufferedReader(new FileReader("測試2.txt"));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
//		3)寫數據
		String line = null;
		while((line=br.readLine())!=null){
			bw.write(line);
			bw.newLine();
			bw.flush();//要刷新!!!
		}
		//停止標誌
		s.shutdownOutput();
		//讀取反饋
		byte []a = new byte[1024];
		int len = is.read(a);
		System.out.println(new String(a, 0, len));
//		4)釋放資源
		s.close();
		
	}

}












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章