網(wǎng)絡(luò)編程
- 網(wǎng)絡(luò)模型
- OSI(Open System Interconnection 開放系統(tǒng)互連)參考模型
- TCP/IP參考模型
- 網(wǎng)絡(luò)通訊要素
- IP地址
- 端口號
- 傳輸協(xié)議
七層簡述(OSI參考模型)
物理層:主要定義物理設(shè)備,網(wǎng)線接口類型砖瞧、光纖接口類型试浙、各種傳輸介質(zhì)的傳輸速率。主要作用是傳輸比特流(就是0、1轉(zhuǎn)化為電流強弱,到達后轉(zhuǎn)為1砰粹、0蛛淋,也成為數(shù)模轉(zhuǎn)換與模數(shù)轉(zhuǎn)換)咙好。這一層的數(shù)據(jù)叫做比特
數(shù)據(jù)鏈路層:主要將物理層接收的數(shù)據(jù)進行MAC地址(網(wǎng)卡地址)的封裝與解封裝。常把這一層的數(shù)據(jù)叫做幀褐荷。這一層工作的設(shè)備是交換機勾效,數(shù)據(jù)通過交換機來傳輸
網(wǎng)絡(luò)層:主要將從下層接收到的數(shù)據(jù)進行IP地址(例如:192.168.0.1)的封裝與解封裝。在這一層工作的設(shè)備是路由器叛甫,常把這一層的數(shù)據(jù)叫做數(shù)據(jù)包
-
傳輸層:定義了一些傳輸數(shù)據(jù)的協(xié)議和端口號(www端口80等)层宫,如:
- TCP(傳輸控制協(xié)議,傳輸效率低其监,可靠性強萌腿,用于傳輸可靠性要求高,數(shù)據(jù)量大的數(shù)據(jù))
- UDP(用戶數(shù)據(jù)報協(xié)議抖苦,與TCP特性相反毁菱,用于傳輸可靠性要求不高,數(shù)據(jù)量小的數(shù)據(jù))
主要是將從下層接收的數(shù)據(jù)進行分段和傳輸锌历,到達目的地址后進行重組贮庞,常把這一層的數(shù)據(jù)叫做段
會話層:通過傳輸層(端口號:傳輸端口和接收端口)建立數(shù)據(jù)傳輸?shù)耐贰V饕谀愕南到y(tǒng)之間發(fā)起會話或者接受會話請求(設(shè)備之間需要互相人事可以是IP也可以是MAC或者是主機名)
表示層:主要是進行對接收的數(shù)據(jù)進行解釋究西、加密與解密窗慎、壓縮與解壓縮等(也就是把計算機能夠識別的東西轉(zhuǎn)換成人能識別的東西,如:圖片卤材、聲音等)
應(yīng)用層:主要是一些終端的應(yīng)用遮斥,比如說FTP(各種文件下載),WEB(IE瀏覽器)扇丛,QQ之類的(可以把它理解成我們在電腦屏幕上可以看到的東西术吗,就是終端應(yīng)用)
網(wǎng)絡(luò)通訊要素
- IP地址:InterAddress
- 網(wǎng)絡(luò)中設(shè)備的標識
- 不易記憶,可用主機名
- 本地回環(huán)地址:127.0.0.1 主機名:localhost
- 端口號
- 用于標識進程的邏輯地址晕拆,不同進程的標識
- 有效端口:065535藐翎,其中01024系統(tǒng)使用或保留端口
- 傳輸協(xié)議
- 通訊的規(guī)則
- 常見協(xié)議:TCP,UDP
TCP和UDP
- UDP:
- 將數(shù)據(jù)即源和目的封裝成數(shù)據(jù)包中实幕,不需要建立連接
- 每個數(shù)據(jù)報的大小限制在64K內(nèi)
- 因無連接吝镣,是不可靠協(xié)議
- 無需要建立連接,速度快
- TCP:
- 建立連接昆庇,形成傳輸數(shù)據(jù)的通道
- 在建立中進行大數(shù)據(jù)量傳輸
- 通過三次握手完成連接末贾,是可靠協(xié)議
- 必須建立連接,效率會稍低
package IPDemo;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class IpDemo {
public static void main(String[] args) throws UnknownHostException {
// 獲取本地主機ip地址對象
InetAddress ip = InetAddress.getLocalHost();
System.out.println(ip.getHostName() + ":" +ip.getHostAddress());
// 獲取其他主機的ip地址對象
ip = InetAddress.getByName("www.baidu.com"); // InetAddress.getByName("SD-20200410UFRP");
// 域名解析
System.out.println(ip.getHostName() + ":" + ip.getHostAddress());
}
}
Socket
- Socket就是為網(wǎng)絡(luò)服務(wù)提供的一種機制
- 通信的兩端都有Socket
- 網(wǎng)絡(luò)通信其實就是Socket間的通信
- 數(shù)據(jù)在兩個Socket間通過IO傳輸
UDP傳輸
- DatagramSocket與DatagramPacket
- 建立發(fā)送端整吆,接收端
- 建立數(shù)據(jù)包
- 調(diào)用Socket的發(fā)送接收方法
- 關(guān)閉Socket
發(fā)送端與接收端是兩個獨立的運行程序
- UDP發(fā)送
package UDP;
import java.io.IOException;
import java.net.*;
public class UDPSendDemo {
public static void main(String[] args) throws IOException {
System.out.println("UDP Socket SendMessage Start 發(fā)送服務(wù)啟動......");
/**
* 創(chuàng)建UDP傳輸?shù)陌l(fā)送端
* 1拱撵、建立UDP的socket服務(wù)
* 2辉川、將要發(fā)送的數(shù)據(jù)封裝到數(shù)據(jù)包中
* 3、通過UDP的socket服務(wù)將數(shù)據(jù)包發(fā)送出去
* 4拴测、關(guān)閉socket服務(wù)
*/
// 1乓旗、UDPSocket服務(wù),使用DatagramSocket對象
DatagramSocket datagramSocket = new DatagramSocket();
// 2集索、將要發(fā)送的數(shù)據(jù)封裝到數(shù)據(jù)包中
String str = "udp傳輸測試數(shù)據(jù)屿愚!";
// 使用DatagramPacket將數(shù)據(jù)封裝到該對象包中
byte[] buf = str.getBytes();
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.82"),10086);
// 3、通過udp的socket服務(wù)將數(shù)據(jù)包發(fā)送出去务荆,使用send方法
datagramSocket.send(datagramPacket);
// 4妆距、關(guān)閉socket服務(wù)
datagramSocket.close();
}
}
- UDP接收
package UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPRecvDemo {
public static void main(String[] args) throws IOException {
System.out.println("UDP Socket ReceiveMessage Start 接收服務(wù)啟動......");
/**
* 創(chuàng)建UDP傳輸?shù)慕邮? * 1、建立UDP的socket服務(wù)
* 2函匕、創(chuàng)建數(shù)據(jù)包娱据,用于存儲接收到的數(shù)據(jù),方便用數(shù)據(jù)包對象的方法解析數(shù)據(jù)
* 3盅惜、用socket服務(wù)的receive方法將接收的數(shù)據(jù)存儲到包中
* 4中剩、通過數(shù)據(jù)包中的方法解析數(shù)據(jù)包中的數(shù)據(jù)
* 5、關(guān)閉資源
*/
// 1抒寂、建立UDP socket服務(wù),接收數(shù)據(jù)必須明確端口號
DatagramSocket datagramSocket = new DatagramSocket(10086);
// 2咽安、創(chuàng)建數(shù)據(jù)包
byte[] buf = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(buf,buf.length);
// 3、使用接收方法將數(shù)據(jù)存儲到數(shù)據(jù)包中
datagramSocket.receive(datagramPacket); // 阻塞式
// 4蓬推、通過數(shù)據(jù)包對象的方法,解析其中的數(shù)據(jù)澡腾,如:端口沸伏,地址,數(shù)據(jù)等內(nèi)容
String ip = datagramPacket.getAddress().getHostAddress();
int port = datagramPacket.getPort();
String dataText = new String(datagramPacket.getData(), 0, datagramPacket.getLength());
System.out.println(ip + ":" + port + ":" + dataText);
// 5动分、關(guān)閉資源
datagramSocket.close();
}
}
UDP聊天室源碼:https://gitee.com/Liu_zimo/JavaTestCode.git
TCP傳輸
- Socket和ServerSocket
- 建立客戶端和服務(wù)端
- 建立連接后毅糟,通過Socket中的IO流進行數(shù)據(jù)的傳輸
- 關(guān)閉Socket
同樣,客戶端與服務(wù)端是兩個獨立的應(yīng)用程序
- TCP客戶端
package TCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
System.out.println("TCP Client Start...");
/**
* Tcp傳輸澜公,客戶端建立的過程
* 1姆另、創(chuàng)建tcp客戶端socket服務(wù)。使用的是socket對象
* 建議該對象一創(chuàng)建就明確目的地坟乾。要連接的主機
* 2迹辐、如果連接建立成功,說明數(shù)據(jù)傳輸通道(socket流)已建立
* socket流:底層建立好的甚侣,有輸入和輸出明吩,通過socket獲取
* 3、使用輸出流殷费,將數(shù)據(jù)寫出
* 4印荔、關(guān)閉資源
*/
// 創(chuàng)建客戶端服務(wù)
Socket socket = new Socket("192.168.1.82", 10086);
// 獲取socket流中的輸出流
OutputStream outputStream = socket.getOutputStream();
// 使用輸出流將指定的數(shù)據(jù)寫出去
outputStream.write("tcp測試數(shù)據(jù)低葫!".getBytes());
// 讀取服務(wù)端返回的數(shù)據(jù)
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
String text = new String(buf, 0, len);
System.out.println(text);
// 關(guān)閉資源
socket.close();
}
}
- TCP服務(wù)端
package TCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
System.out.println("TCP Server start...");
/**
* 建立TCP服務(wù)端
* 1、創(chuàng)建服務(wù)端socket服務(wù)仍律,通過ServerSocket對象
* 2嘿悬、服務(wù)端必須對外提供一個端口,否則客戶端無法連接
* 3水泉、獲取連接的客戶端對象
* 4善涨、使用客戶端對象獲取socket流,讀取客戶端發(fā)來的消息茶行,打印處理
* 5躯概、關(guān)閉資源:關(guān)客戶端,關(guān)服務(wù)端
*/
// 創(chuàng)建服務(wù)端對象
ServerSocket serverSocket = new ServerSocket(10086);
// 獲取連接的客戶端對象
Socket socket = serverSocket.accept();
String ip = socket.getInetAddress().getHostAddress();
int port = socket.getPort();
// 通過socket對象獲取輸入流畔师,讀取客戶端發(fā)來的數(shù)據(jù)
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
String text = new String(buf, 0, len);
System.out.println(ip + ":" + port + "/server :" + text);
// 客戶端輸出流返回數(shù)據(jù)
OutputStream outputStream = socket.getOutputStream();
outputStream.write("收到".getBytes());
// 關(guān)閉資源:一般服務(wù)端阻塞一直讀取客戶端
socket.close();
serverSocket.close();
}
}
-
常見的客戶端:
瀏覽器:IE娶靡,Google Chrome
-
常見的服務(wù)端:
服務(wù)器:Tomcat
客戶端給服務(wù)端發(fā)送的請求
-
GET / HTTP/1.1
請求行:<u>請求方式 /www/index.html(請求資源路徑) http協(xié)議版本</u> -
Accept:image/gif, image/jpeg, ..., */*
請求消息頭:<u>屬性名:屬性值</u> Accept-Language: zh-cn,zu;q=0.5
Accept-Encoding:gzip,deflate
User-Agent:Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2)
Host:192.168.1.82: 10086
Connection: Keep-Alive
// 請求頭和請求體之間有空行作為分割-------------
-
<html><title></title><body>hahahahahah</body></html>
請求體:具體信息
常見網(wǎng)絡(luò)結(jié)構(gòu)
-
C/S:Client/Server
-
特點:該結(jié)構(gòu)的軟件,客戶端和服務(wù)端都需要編寫
開發(fā)成本較高看锉,維護較為麻煩
好處:客戶端在本地可以分擔(dān)一部分運算
-
-
B/S:Browser/Server
-
特點:該結(jié)構(gòu)的軟件姿锭,只開發(fā)服務(wù)器端,不開發(fā)客戶端伯铣,客戶端由瀏覽器取代
開發(fā)成本相對低呻此,維護較為簡單
- 缺點:所有的運算都要在服務(wù)端完成
-