黑馬程式設計師之 --- 網路程式設計
------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a>、期待與您交流! ----------
網路程式設計概述
計算機網路
是指將地理位置不同的具有獨立功能的多臺計算機及其外部裝置,通過通訊線路連線起來,在網路作業系統,網路管理軟體及網路通訊協議的管理和協調下,實現資源共享和資訊傳遞的計算機系統。
網路程式設計
就是用來實現網路互連的不同計算機上執行的程式間可以進行資料交換。
網路模型
計算機網路之間以何種規則進行通訊,就是網路模型研究問題。
網路模型一般是指
OSI(Open System Interconnection開放系統互連)參考模型
TCP/IP參考模型
網路模型7層概述:
1.物理層:主要定義物理裝置標準,如網線的介面型別、光纖的介面型別、各種傳輸介質的傳輸速率等。它的主要作用是傳輸位元流(就是由1、0轉化為電流強弱來進行傳輸,到達目的地後在轉化為1、0,也就是我們常說的數模轉換與模數轉換)。這一層的資料叫做位元。
2. 資料鏈路層:主要將從物理層接收的資料進行MAC地址(網絡卡的地址)的封裝與解封裝。常把這一層的資料叫做幀。在這一層工作的裝置是交換機,資料通過交換機來傳輸。
3. 網路層:主要將從下層接收到的資料進行IP地址(例192.168.0.1)的封裝與解封裝。在這一層工作的裝置是路由器,常把這一層的資料叫做資料包。
4. 傳輸層:定義了一些傳輸資料的協議和埠號(WWW埠80等),如:TCP(傳輸控制協議,傳輸效率低,可靠性強,用於傳輸可靠性要求高,資料量大的資料),UDP(使用者資料報協議,與TCP特性恰恰相反,用於傳輸可靠性要求不高,資料量小的資料,如QQ聊天資料就是通過這種方式傳輸的)。 主要是將從下層接收的資料進行分段和傳輸,到達目的地址後再進行重組。常常把這一層資料叫做段。
5.會話層:通過傳輸層(埠號:傳輸埠與接收埠)建立資料傳輸的通路。主要在你的系統之間發起會話或者接受會話請求(裝置之間需要互相認識可以是
6.表示層:主要是進行對接收的資料進行解釋、加密與解密、壓縮與解壓縮等(也就是把計算機能夠識別的東西轉換成人能夠能識別的東西(如圖片、聲音等)。
7.應用層: 主要是一些終端的應用,比如說FTP(各種檔案下載),WEB(IE瀏覽),QQ之類的(可以把它理解成我們在電腦螢幕上可以看到的東西.就是終端應用)。
網路通訊三要素
IP地址:InetAddress
網路中裝置的標識,不易記憶,可用主機名
埠號
用於標識程序的邏輯地址,不同程序的標識
傳輸協議
通訊的規則
常見協議:TCP,UDP
網路程式設計的三個要素:
IP地址:
有32位或者128位表示, 常用的IP地址是32位 也就是IPV4, 128位代表IPV6
IP地址的分類:
A: 1.0.0.1 -- 127.255.255.254 10.x.x.x 是私有地址
B類 128.0.0.1---191.255.255.254 172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
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
埠號:
0-65535 其中0-1024為系統保留埠
//檢視埠方式
//360
//DOS命令 netstat -a
傳輸協議:
UDP協議:
將資料來源和目的封裝成資料包中,不需要建立連線;
每個資料報的大小在限制在64k;因無連線,是不可靠協議;
不需要建立連線,速度快
打電話,QQ聊天
TCP協議:
建立連線,形成傳輸資料的通道;
在連線中進行大資料量傳輸;通過三次握手完成連線,是可靠協議;
必須建立連線,效率會稍低
資料的傳輸
Socket
Socket套接字:
網路上具有唯一標識的IP地址和埠號組合在一起才能構成唯一能識別的識別符號套接字。
Socket原理機制:
通訊的兩端都有Socket。
網路通訊其實就是Socket間的通訊。
資料在兩個Socket間通過IO傳輸。
使用UDP進行資料的傳輸:
傳送端:
1: 建立UDP協議的傳送端DatagramSocket物件
2: 把要傳送的資料 ,封裝成 資料報包 使用DatagramPacket物件完成
3: 傳送資料報包, send(dp)方法
4: 關閉Socket流, 使用close()方法
程式碼實現:
public class UDPSend {
public static void main(String[] args) throws IOException {
//建立傳送端Socket物件
DatagramSocket ds = new DatagramSocket();
while (true) {
//準備傳送的資料,封裝成資料報包
//System.in
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
//判斷是否為886,結束輸入資料
if ("886".equals(line)) {
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.25.122"), 12306);
//傳送資料
ds.send(dp);
}
//關閉Socket物件
ds.close();
}
}
接收端:
1: 建立UDP協議的接收端DatagramSocket物件
2; 建立空的資料報包, 用來儲存接收到的資料
3: 接收資料,把資料儲存到空的資料報包中
4: 解析資料報包中的資料
獲取IP地址 getAddress();
獲取資料: getData();
獲取資料的長度: getLength();
5: 關閉Socket流,使用close()方法
程式碼實現:
public class UDPRecevie {
public static void main(String[] args) throws IOException {
//建立Socket物件
DatagramSocket ds = new DatagramSocket(12306);
while (true) {
//建立一個空的資料報包,一用來接收資料
byte[] buffer = new byte[1024];
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
//接收資料,把資料儲存到空的資料報包中
ds.receive(dp);
//看內容
byte[] data = dp.getData();
int len = dp.getLength();
String ip = dp.getAddress().getHostAddress();
System.out.println("IP:" + ip + "---data:" + new String(data, 0 , len));
}
//關閉Socket物件
//ds.close();
}
}
使用TCP進行資料的傳輸:
客戶端;
1: 建立客戶端的Socket物件
2: 準備要傳送的資料
3: 通過Socket物件中的輸出流,完成資料的傳送
4: 告知伺服器 ,資料已傳送完畢, shutdownOutput()
5: 獲取伺服器的反饋資訊
6; 關閉Socket流
程式碼實現:
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
// 建立客戶端的Socket物件
Socket s = new Socket("192.168.25.122", 19527);
// 準備傳送的資料
String data = "哈哈";
// 傳送資料
OutputStream os = s.getOutputStream();
os.write(data.getBytes());
//告訴伺服器一聲,客戶端的資料傳送完畢
//public void shutdownOutput() 禁用此套接字的輸出流
s.shutdownOutput();
//獲取服務端的反饋資訊
//s.getInputStream();
BufferedReader serverBR = new BufferedReader(new InputStreamReader(s.getInputStream()));
String server = serverBR.readLine();
System.out.println("反饋資訊:" + server);
// 關閉Socket物件
os.close();
s.close();
}
}
伺服器端:
1: 建立伺服器端ServerSocket物件
2: 等待客戶端的連線
3: 建立執行緒物件,並啟動,通過每個執行緒物件,來完成與客戶端Socket物件的資料傳輸
a: 獲取IP地址
String ip = s.getInetAddress().getHostAddress();
b: 獲取資料
1): 獲取客戶端的輸入流物件
2): 通過輸入流物件, 讀取流中的資料
3): 把資料進行處理(列印,儲存到檔案中)
c: 編寫客戶端反饋資訊
1): 獲取客戶端的輸出流物件
2): 寫 給客戶端的反饋資訊
d: 關閉客戶端Socket流
程式碼實現:
public class TCPServer {
public static void main(String[] args) throws IOException {
//建立伺服器端ServerSocket物件
ServerSocket ss = new ServerSocket(19527);
//開啟伺服器端,等待客戶端Socket物件的連線
//獲取客戶端的Socket物件
Socket s = ss.accept();
//從客戶端的Socket物件中,獲取 輸入流物件。列印資料
String ip = s.getInetAddress().getHostAddress();// 獲取客戶端的IP地址
System.out.println("ip:"+ ip);
//獲取客戶端傳送過來的資料
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//給客戶端反饋資訊
// s.getOutputStream();
OutputStream os = s.getOutputStream();
os.write("我收到了資料,告訴你一聲".getBytes());
//關閉客戶端的Socket物件
s.close();
}
}
多執行緒版本:UDP聊天室
//傳送端
public class SendRunnable implements Runnable {
//傳送端Socket物件
private DatagramSocket ds;
public SendRunnable(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
while (true) {
try {
//建立Socket物件
//準備資料
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
//判斷是否為886, 結束輸入
if ("886".equals(line)) {
break;
}
byte[] buf = line.getBytes();
//廣播地址
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.25.255"), 9999);
//傳送資料
ds.send(dp);
//關閉Socket物件
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//接收端
public class ReceiveRunnable implements Runnable {
// 接收端的Socket物件
private DatagramSocket ds;
public ReceiveRunnable(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
while (true) {
try {
// 建立Socket物件
// 建立空的資料報包
byte[] buffer = new byte[1024];
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
// 接收資料, 儲存到 空的資料報包中
ds.receive(dp);
// 顯示資料
// byte[] data = dp.getData(); //資料
// int len = dp.getLength();
// String ip = dp.getAddress().getHostAddress();//ip地址
// System.out.println("IP:" + ip + "---data:" + new String(data, 0 ,
// len));
System.out.println("IP:" + dp.getAddress().getHostAddress()
+ "---data:" + new String(dp.getData(), 0, dp.getLength()));
// 關閉Socket物件
//ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//聊天室
public class ChatRoom {
public static void main(String[] args) throws IOException {
//建立傳送端和接收端的Socket物件
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receiveSocket = new DatagramSocket(9999);
//建立Runnable實現類物件
SendRunnable send = new SendRunnable(sendSocket);
ReceiveRunnable receive = new ReceiveRunnable(receiveSocket);
//建立傳送端和接收端執行緒物件
Thread sendThread = new Thread(send);
Thread receiveThread = new Thread(receive);
//啟動執行緒
sendThread.start();
receiveThread.start();
}
}
TCP:
/*
* 客戶端鍵盤錄入,伺服器輸出到控制檯
*/
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//建立客戶端Socket物件
Socket s = new Socket("192.168.25.122", 12345);
//準備傳送的資料
//System.in
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
//傳送資料
//s.getOutputStream();
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);//開啟自動重新整理
pw.println(line);
//告訴伺服器,要傳送的資料已完成
s.shutdownOutput();
//獲取伺服器的反饋資訊
BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
String client = brClient.readLine();
System.out.println("反饋資訊:" + client);
//關閉Socket流
s.close();
}
}
/*
* 客戶端鍵盤錄入,伺服器輸出到控制檯
*/
public class TCPServer {
public static void main(String[] args) throws IOException {
//建立伺服器端ServerSocket物件
ServerSocket ss = new ServerSocket(12345);
while (true) {
//每來一次客戶端Socket物件,我們就建立一個執行緒物件,與客戶端進行交流
Socket s = ss.accept();
ServerRunnable sr = new ServerRunnable(s);
//建立一個執行緒物件,用來和客戶端互動
Thread t = new Thread(sr);
t.start();
}
}
}
/*
* 每一個執行緒物件,要做的操作
*/
public class ServerRunnable implements Runnable {
//代表著 正在連線上 伺服器的客戶端Socket物件
private Socket s;
public ServerRunnable(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
//獲取客戶端Socket的IP地址
//s.getInetAddress();
String ip = s.getInetAddress().getHostAddress();
System.out.println("IP:" + ip);
//獲取客戶端Socket物件的輸入流
//s.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//通過輸入流, 獲取客戶端傳送過來的資料
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//需要給客戶端反饋資訊
//s.getOutputStream();
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);//開啟自動重新整理
pw.println("朕已收到");
//關閉客戶端的Socket流
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}