?
軟件結(jié)構(gòu)
C/S結(jié)構(gòu) :client/sever是指客戶端和服務(wù)器結(jié)構(gòu)。常見程序有QQ、迅雷等軟件。
B/S結(jié)構(gòu) :browser/sever是指瀏覽器和服務(wù)器結(jié)構(gòu)。常見瀏覽器有谷歌、火狐等。
Web應(yīng)用系統(tǒng)開發(fā)的兩種流行架構(gòu)
兩種架構(gòu)各有優(yōu)勢(shì),但是無(wú)論哪種架構(gòu),都離不開網(wǎng)絡(luò)的支持。網(wǎng)絡(luò)編程,就是在一定的協(xié)議下,實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)的通信的程序。
網(wǎng)絡(luò)通信協(xié)議
網(wǎng)絡(luò)通信協(xié)議:通過(guò)計(jì)算機(jī)網(wǎng)絡(luò)可以使多臺(tái)計(jì)算機(jī)實(shí)現(xiàn)連接,位于同一個(gè)網(wǎng)絡(luò)中的計(jì)算機(jī)在進(jìn)行連接和通信時(shí)需要遵守一定的規(guī)則。在計(jì)算機(jī)網(wǎng)絡(luò)中,這些連接和通信的規(guī)則被稱為網(wǎng)絡(luò)通信協(xié)議,它對(duì)數(shù)據(jù)的傳輸格式、傳輸速率、傳輸步驟等做了統(tǒng)一規(guī)定,通信雙方必須同時(shí)遵守才能完成數(shù)據(jù)交換。
TCP/IP協(xié)議: 傳輸控制協(xié)議/因特網(wǎng)互聯(lián)協(xié)議( Transmission Control Protocol/Internet Protocol),是Internet最基本、最廣泛的協(xié)議。它定義了計(jì)算機(jī)如何連入因特網(wǎng),以及數(shù)據(jù)如何在它們之間傳輸?shù)臉?biāo)準(zhǔn)。它的內(nèi)部包含一系列的用于處理數(shù)據(jù)通信的協(xié)議,并采用了4層的分層模型,每一層都呼叫它的下一層所提供的協(xié)議來(lái)完成自己的需求。
上圖中,TCP/IP協(xié)議中的四層分別是應(yīng)用層、傳輸層、網(wǎng)絡(luò)層和鏈路層,每層分別負(fù)責(zé)不同的通信功能。
鏈路層:鏈路層是用于定義物理傳輸通道,通常是對(duì)某些網(wǎng)絡(luò)連接設(shè)備的驅(qū)動(dòng)協(xié)議,例如針對(duì)光纖、網(wǎng)線提供的驅(qū)動(dòng)。
網(wǎng)絡(luò)層:網(wǎng)絡(luò)層是整個(gè)TCP/IP協(xié)議的核心,它主要用于將傳輸?shù)臄?shù)據(jù)進(jìn)行分組,將分組數(shù)據(jù)發(fā)送到目標(biāo)計(jì)算機(jī)或者網(wǎng)絡(luò)。
傳輸層:主要使網(wǎng)絡(luò)程序進(jìn)行通信,在進(jìn)行網(wǎng)絡(luò)通信時(shí),可以采用TCP協(xié)議,也可以采用UDP協(xié)議。
應(yīng)用層:主要負(fù)責(zé)應(yīng)用程序的協(xié)議,例如HTTP協(xié)議、FTP協(xié)議等。
協(xié)議分類
通信的協(xié)議還是比較復(fù)雜的,java.net 包中包含的類和接口,它們提供低層次的通信細(xì)節(jié)。我們可以直接使用這些類和接口,來(lái)專注于網(wǎng)絡(luò)程序開發(fā),而不用考慮通信的細(xì)節(jié)。
java.net 包中提供了兩種常見的網(wǎng)絡(luò)協(xié)議的支持:
UDP:用戶數(shù)據(jù)報(bào)協(xié)議(User Datagram Protocol)。UDP是無(wú)連接通信協(xié)議,即在數(shù)據(jù)傳輸時(shí),數(shù)據(jù)的發(fā)送端和接收端不建立邏輯連接。簡(jiǎn)單來(lái)說(shuō),當(dāng)一臺(tái)計(jì)算機(jī)向另外一臺(tái)計(jì)算機(jī)發(fā)送數(shù)據(jù)時(shí),發(fā)送端不會(huì)確認(rèn)接收端是否存在,就會(huì)發(fā)出數(shù)據(jù),同樣接收端在收到數(shù)據(jù)時(shí),也不會(huì)向發(fā)送端反饋是否收到數(shù)據(jù)。
由于使用UDP協(xié)議消耗資源小,通信效率高,所以通常都會(huì)用于音頻、視頻和普通數(shù)據(jù)的傳輸例如視頻會(huì)議都使用UDP協(xié)議,因?yàn)檫@種情況即使偶爾丟失一兩個(gè)數(shù)據(jù)包,也不會(huì)對(duì)接收結(jié)果產(chǎn)生太大影響。
但是在使用UDP協(xié)議傳送數(shù)據(jù)時(shí),由于UDP的面向無(wú)連接性,不能保證數(shù)據(jù)的完整性,因此在傳輸重要數(shù)據(jù)時(shí)不建議使用UDP協(xié)議。
UDP的交換過(guò)程如下圖所示:
特點(diǎn):數(shù)據(jù)被限制在64kb以內(nèi),超出這個(gè)范圍就不能發(fā)送了。
數(shù)據(jù)報(bào)(Datagram):網(wǎng)絡(luò)傳輸?shù)幕締挝?/p>
TCP:傳輸控制協(xié)議 (Transmission Control Protocol)。TCP協(xié)議是面向連接的通信協(xié)議,即傳輸數(shù)據(jù)之前,在發(fā)送端和接收端建立邏輯連接,然后再傳輸數(shù)據(jù),它提供了兩臺(tái)計(jì)算機(jī)之間可靠無(wú)差錯(cuò)的數(shù)據(jù)傳輸。
在TCP連接中必須要明確客戶端與服務(wù)器端,由客戶端向服務(wù)端發(fā)出連接請(qǐng)求,每次連接的創(chuàng)建都需要經(jīng)過(guò)“三次握手”。
三次握手: TCP協(xié)議中,在發(fā)送數(shù)據(jù)的準(zhǔn)備階段,客戶端與服務(wù)器之間的三次交互,以保證連接的可靠。
第一次握手,客戶端向服務(wù)器端發(fā)出連接請(qǐng)求,等待服務(wù)器確認(rèn)。
第二次握手,服務(wù)器端向客戶端回送一個(gè)響應(yīng),通知客戶端收到了連接請(qǐng)求。
第三次握手,客戶端再次向服務(wù)器端發(fā)送確認(rèn)信息,確認(rèn)連接。
?完成三次握手,連接建立后,客戶端和服務(wù)器就可以開始進(jìn)行數(shù)據(jù)傳輸了。由于這種面向連接的特性,TCP協(xié)議可以保證傳輸數(shù)據(jù)的安全,所以應(yīng)用十分廣泛,例如下載文件、瀏覽網(wǎng)頁(yè)等。
網(wǎng)絡(luò)編程三要素
協(xié)議、IP地址、端口號(hào)
協(xié)議:計(jì)算機(jī)網(wǎng)絡(luò)通信必須遵守的規(guī)則,已經(jīng)介紹過(guò)了。
IP地址:指互聯(lián)網(wǎng)協(xié)議地址(Internet Protocol Address),俗稱IP。 IP地址用來(lái)給一個(gè)網(wǎng)絡(luò)中的計(jì)算機(jī)設(shè)備做唯一的編號(hào)。假如我們把 “個(gè)人電腦” 比作 “一臺(tái)電話” 的話,那么 “IP地址” 就相當(dāng)于 “電話號(hào)碼”。
【IP地址分類 win+r —— cmd】
IPv4:是一個(gè)32位的二進(jìn)制數(shù),通常被分為4個(gè)字節(jié),表示成a.b.c.d 的形式,例如192.168.65.100 。
其中a、b、c、d都是0~255之間的十進(jìn)制整數(shù),那么最多可以表示42億個(gè)。
IPv6:由于互聯(lián)網(wǎng)的蓬勃發(fā)展,IP地址的需求量愈來(lái)愈大,但是網(wǎng)絡(luò)地址資源有限,使得IP的分配越發(fā)緊張。
為了擴(kuò)大地址空間,擬通過(guò)IPv6重新定義地址空間,采用128位地址長(zhǎng)度,每16個(gè)字節(jié)一組,分成8組十六進(jìn)制數(shù),表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789,號(hào)稱可以為全世界的每一粒沙子編上一個(gè)網(wǎng)址,這樣就解決了網(wǎng)絡(luò)地址資源數(shù)量不夠的問(wèn)題。
常用命令
查看本機(jī)IP地址,在控制臺(tái)輸入:
ipconfig
檢查網(wǎng)絡(luò)是否連通,在控制臺(tái)輸入:
ping 空格 IP地址
ping 220.181.57.216
特殊的IP地址
本機(jī)IP地址:127.0.0.1、localhost 。
端口號(hào)
網(wǎng)絡(luò)的通信,本質(zhì)上是兩個(gè)進(jìn)程(應(yīng)用程序)的通信。每臺(tái)計(jì)算機(jī)都有很多的進(jìn)程,那么在網(wǎng)絡(luò)通信時(shí),如何區(qū)分這些進(jìn)程呢?
如果說(shuō)IP地址可以唯一標(biāo)識(shí)網(wǎng)絡(luò)中的設(shè)備,那么端口號(hào)就可以唯一標(biāo)識(shí)設(shè)備中的進(jìn)程(應(yīng)用程序)了。
端口號(hào):用兩個(gè)字節(jié)表示的整數(shù),它的取值范圍是0~65535
其中,0~1023之間的端口號(hào)用于一些知名的網(wǎng)絡(luò)服務(wù)和應(yīng)用,普通的應(yīng)用程序需要使用1024以上的端口號(hào)。如果端口號(hào)被另外一個(gè)服務(wù)或應(yīng)用所占用,會(huì)導(dǎo)致當(dāng)前程序啟動(dòng)失敗。
利用協(xié)議+IP地址+端口號(hào) 三元組合,就可以標(biāo)識(shí)網(wǎng)絡(luò)中的進(jìn)程了,那么進(jìn)程間的通信就可以利用這個(gè)標(biāo)識(shí)與其它進(jìn)程進(jìn)行交互。
TCP通信程序
概述
TCP通信能實(shí)現(xiàn)兩臺(tái)計(jì)算機(jī)之間的數(shù)據(jù)交互,通信的兩端,要嚴(yán)格區(qū)分為客戶端(Client)與服務(wù)端(Server)。
兩端通信時(shí)步驟:
1、服務(wù)端程序,需要事先啟動(dòng),等待客戶端的連接。
2、客戶端主動(dòng)連接服務(wù)器端,連接成功才能通信。服務(wù)端不可以主動(dòng)連接客戶端。
在Java中,提供了兩個(gè)類用于實(shí)現(xiàn)TCP通信程序:
1、客戶端:java.net.Socket 類表示。創(chuàng)建Socket對(duì)象,向服務(wù)端發(fā)出連接請(qǐng)求,服務(wù)端響應(yīng)請(qǐng)求,兩者建立連接開始通信。
2、服務(wù)端:java.net.ServerSocket 類表示。創(chuàng)建ServerSocket對(duì)象,相當(dāng)于開啟一個(gè)服務(wù),并等待客戶端的連接。
Socket類
Socket 類:該類實(shí)現(xiàn)客戶端套接字,套接字指的是兩臺(tái)設(shè)備之間通訊的端點(diǎn)。
構(gòu)造方法
public Socket(String host, int port) :創(chuàng)建套接字對(duì)象并將其連接到指定主機(jī)上的指定端口號(hào)。如果指定的host是null ,則相當(dāng)于指定地址為回送地址。
小貼士:回送地址(127.x.x.x) 是本機(jī)回送地址(Loopback Address),主要用于網(wǎng)絡(luò)軟件測(cè)試以及本地機(jī)進(jìn)程間通信,無(wú)論什么程序,一旦使用回送地址發(fā)送數(shù)據(jù),立即返回,不進(jìn)行任何網(wǎng)絡(luò)傳輸。
構(gòu)造舉例,代碼如下(示例):
Socket client = new Socket("127.0.0.1", 6666);
成員方法
public InputStream getInputStream() : 返回此套接字的輸入流。
如果此Scoket具有相關(guān)聯(lián)的通道,則生成的InputStream 的所有操作也關(guān)聯(lián)該通道。
關(guān)閉生成的InputStream也將關(guān)閉相關(guān)的Socket。
public OutputStream getOutputStream() : 返回此套接字的輸出流。
如果此Scoket具有相關(guān)聯(lián)的通道,則生成的OutputStream 的所有操作也關(guān)聯(lián)該通道。
關(guān)閉生成的OutputStream也將關(guān)閉相關(guān)的Socket。
public void close() :關(guān)閉此套接字。
一旦一個(gè)socket被關(guān)閉,它不可再使用。
關(guān)閉此socket也將關(guān)閉相關(guān)的InputStream和OutputStream 。
public void shutdownOutput() : 禁用此套接字的輸出流。
任何先前寫出的數(shù)據(jù)將被發(fā)送,隨后終止輸出流。
ServerSocket類
ServerSocket類:這個(gè)類實(shí)現(xiàn)了服務(wù)器套接字,該對(duì)象等待通過(guò)網(wǎng)絡(luò)的請(qǐng)求。
構(gòu)造方法
public ServerSocket(int port) :使用該構(gòu)造方法在創(chuàng)建ServerSocket對(duì)象時(shí),就可以將其綁定到一個(gè)指定的端口號(hào)上,參數(shù)port就是端口號(hào)。
構(gòu)造舉例,代碼如下(示例):
ServerSocket server = new ServerSocket(6666);
成員方法
public Socket accept() :偵聽并接受連接,返回一個(gè)新的Socket對(duì)象,用于和客戶端實(shí)現(xiàn)通信。該方法會(huì)一直阻塞直到建立連接。
簡(jiǎn)單的TCP網(wǎng)絡(luò)程序
TCP通信分析圖解
1、【服務(wù)端】啟動(dòng),創(chuàng)建ServerSocket對(duì)象,等待連接。
2、【客戶端】啟動(dòng),創(chuàng)建Socket對(duì)象,請(qǐng)求連接。
3、【服務(wù)端】接收連接,調(diào)用accept方法,并返回一個(gè)Socket對(duì)象。
4、【客戶端】Socket對(duì)象,獲取OutputStream,向服務(wù)端寫出數(shù)據(jù)。
5、【服務(wù)端】Scoket對(duì)象,獲取InputStream,讀取客戶端發(fā)送的數(shù)據(jù)。
到此,客戶端向服務(wù)端發(fā)送數(shù)據(jù)成功。
自此,服務(wù)端向客戶端回寫數(shù)據(jù)。
6、【服務(wù)端】Socket對(duì)象,獲取OutputStream,向客戶端回寫數(shù)據(jù)。
7、【客戶端】Scoket對(duì)象,獲取InputStream,解析回寫數(shù)據(jù)。
8、【客戶端】釋放資源,斷開連接。
客戶端向服務(wù)器發(fā)送數(shù)據(jù)
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientTCP {
public static void main(String[] args) throws Exception {
//2.創(chuàng)建客戶端Socket對(duì)象,請(qǐng)求連接
System.out.println("啟動(dòng)客戶端,發(fā)起連接。。。。。");
Socket client = new Socket("localhost",10086);
//創(chuàng)建套接字對(duì)象client并將其連接到指定主機(jī)localhost上的指定端口號(hào)10086
//4.客戶端再次向服務(wù)器端寫出數(shù)據(jù)
OutputStream os = client.getOutputStream(); //返回此套接字的輸出流
os.write("你好服務(wù)器,我我是客戶端,我發(fā)TCP數(shù)據(jù)了".getBytes());
System.out.println("-----------------------------------------");
//7.客戶端獲取InputStream,解析寫入的數(shù)據(jù)
InputStream is = client.getInputStream();
byte[] b = new byte[1024];
int len = is.read(b);
String msg = new String(b,0,len);
System.out.println(msg);
is.close();
os.close();//關(guān)閉資源
client.close();
}
}
服務(wù)器端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SeverTCP {
//1.服務(wù)器端等待客戶端連接
public static void main(String[] args) throws IOException {
System.out.println("啟動(dòng)服務(wù)器,等待客戶端連接。。。。。");
//3.接收請(qǐng)求,服務(wù)器端向客戶端回返回一個(gè)Socket對(duì)象
ServerSocket ss = new ServerSocket(10086);//創(chuàng)建ServerSocket,綁定10086端口,等待連接
Socket server = ss.accept();//偵聽并接受連接,返回一個(gè)新的Socket對(duì)象,用于和客戶端實(shí)現(xiàn)通信
InputStream is = server.getInputStream();//獲取輸入流
//5.讀取客戶端發(fā)送的數(shù)據(jù)
byte[] b = new byte[1024];
int len = is.read(b);
String msg = new String(b,0,len);
System.out.println(msg);
System.out.println("-----------------------------------------------");
//6.服務(wù)器端獲取OutputStream,向客戶端寫數(shù)據(jù)
OutputStream os = server.getOutputStream();
os.write("我是服務(wù)器,現(xiàn)在給你返回一些數(shù)據(jù),請(qǐng)查收~~~~~".getBytes());
//關(guān)閉資源
os.close();
is.close();
server.close();
}
}
文件上傳
1、【客戶端】輸入流,從硬盤讀取文件數(shù)據(jù)到程序中。
2、【客戶端】輸出流,寫出文件數(shù)據(jù)到服務(wù)端。
3、【服務(wù)端】輸入流,讀取文件數(shù)據(jù)到服務(wù)端程序。
4、【服務(wù)端】輸出流,寫出文件數(shù)據(jù)到服務(wù)器硬盤中。
服務(wù)端實(shí)現(xiàn):
public class FileUpload_Server {
public static void main(String[] args) throws IOException {
System.out.println("服務(wù)器 啟動(dòng)..... ");
// 1. 創(chuàng)建服務(wù)端ServerSocket
ServerSocket serverSocket = new ServerSocket(6666);
// 2. 建立連接
Socket accept = serverSocket.accept();
// 3. 創(chuàng)建流對(duì)象
// 3.1 獲取輸入流,讀取文件數(shù)據(jù)
BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
// 3.2 創(chuàng)建輸出流,保存到本地 .
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream());
// 4. 讀寫數(shù)據(jù)
byte[] b = new byte[1024 * 8];
int len;
while ((len = bis.read(b)) != -1) {
bos.write(b, 0, len);
}
//5. 關(guān)閉 資源
bos.close();
bis.close();
accept.close();
System.out.println("文件上傳已保存");
}
}
客戶端實(shí)現(xiàn):
public class FileUPload_Client {
public static void main(String[] args) throws IOException {
// 1.創(chuàng)建流對(duì)象
// 1.1 創(chuàng)建輸入流,讀取本地文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg"));
// 1.2 創(chuàng)建輸出流,寫到服務(wù)端
Socket socket = new Socket("localhost", 6666);
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//2.寫出數(shù)據(jù).
byte[] b = new byte[1024 * 8 ];
int len ;
while (( len = bis.read(b))!=-1) {
bos.write(b, 0, len);
bos.flush();
}
System.out.println("文件發(fā)送完畢");
// 3.釋放資源
bos.close();
socket.close();
bis.close();
System.out.println("文件上傳完畢 ");
}
}
BIO 、 NIO 與 AIO
菜鳥教程 (runoob.com) | Java 網(wǎng)絡(luò)編程文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-528880.html
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-528880.html
到了這里,關(guān)于Java面向?qū)ο蟪绦蜷_發(fā)——網(wǎng)絡(luò)編程入門知識(shí)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!