Web發(fā)展中通信方式
簡單通信
不同請求
復(fù)雜請求
??回顧 Socket 編程給我們最大的感受,是可以在多臺電腦之間進(jìn)行數(shù)據(jù)的傳輸,這就是網(wǎng)絡(luò)編程的開端和基礎(chǔ),通過客戶端請求服務(wù)器端通信,直觀了解 Web 編程。
Server
/**
* 服務(wù)端,接收客戶端請求并給出簡單的響應(yīng)
* @author Cushier
*
*/publicclassServer{publicstaticvoidmain(String[]args)throwsIOException{// 創(chuàng)建服務(wù)器,指定端口ServerSocket(int port)ServerSocket socket=newServerSocket(8888);// 接收客戶端連接Socket client=socket.accept();System.out.println("******************");// 獲取數(shù)據(jù)的輸入流InputStream is=client.getInputStream();// 使用緩沖字符輸入流BufferedReader br=newBufferedReader(newInputStreamReader(is));String msg="";while((msg=br.readLine())!=null){System.out.println(msg);}br.close();}}
Client
/**
* 客戶端:向服務(wù)器發(fā)送請求,并發(fā)送簡單的消息
* @author Cushier
*
*/publicclassClient{publicstaticvoidmain(String[]args)throwsUnknownHostException,IOException{// 創(chuàng)建客戶端 必須指定服務(wù)器+端口Socket client=newSocket("localhost",8888);// 發(fā)送消息 請求資源// 獲取輸出流OutputStream os=client.getOutputStream();// 使用緩沖字符輸出流BufferedWriter br=newBufferedWriter(newOutputStreamWriter(os));// 寫出消息,發(fā)送內(nèi)容String msg="Hello, I am Client, I need some resources";br.write(msg);br.close();}}
服務(wù)端控制臺:
從上面的例子總結(jié)通信條件如下:
需要有服務(wù)器端(server):等待被請求,需要暴露 ip 和 port
需要有客戶端(client):主動發(fā)起請求,知曉服務(wù)端的 ip 和 port
通信規(guī)則(協(xié)議):TCP/IP 協(xié)議
ip?用于定位計(jì)算機(jī);端口號(定位程序),用于標(biāo)識進(jìn)程的邏輯地址,不同進(jìn)程的標(biāo)志;有效端口:0~65535,其中 0~1024 由系統(tǒng)使用或者保留端口,開發(fā)中建議使用 1024 以上的端口。
Client
/**
* 客戶端:向服務(wù)器發(fā)送請求,發(fā)送不同的請求
* @author Cushier
*
*/publicclassClient{publicstaticvoidmain(String[]args)throwsIOException{// 通過系統(tǒng)默認(rèn)類型的 SocketImpl 創(chuàng)建未連接套接字Socket socket=newSocket();// 此類實(shí)現(xiàn) IP 套接字地址(IP 地址 + 端口號)。它還可以是一個(gè)對(主機(jī)名 + 端口號),在此情況下,將嘗試解析主機(jī)名SocketAddress address=newInetSocketAddress("localhost",8898);// 將此套接字連接到服務(wù)器,并指定一個(gè)超時(shí)值。或者不指定超時(shí)時(shí)間socket.connect(address,1000);OutputStream os=socket.getOutputStream();os.write("time".getBytes());os.flush();socket.close();}}
Server
/**
* 服務(wù)端
* public class ServerSocketextends Object:此類實(shí)現(xiàn)服務(wù)器套接字。
* 服務(wù)器套接字等待請求通過網(wǎng)絡(luò)傳入。
* 它基于該請求執(zhí)行某些操作,然后可能向請求者返回結(jié)果。
*
* @author Cushier
*
*/publicclassServer{publicstaticvoidmain(String[]args)throwsIOException{// 創(chuàng)建綁定到特定端口的服務(wù)器套接字。ServerSocket server=newServerSocket(8898);// Socket accept() 偵聽并接受到此套接字的連接。Socket client=server.accept();System.out.println("接收到連接");InputStream is=client.getInputStream();BufferedInputStream bis=newBufferedInputStream(is);byte[]req=newbyte[1024];// 接收客戶端請求intlen=bis.read(req);String reqStr=newString(req,0,len);System.out.println(reqStr);if(reqStr.equals("money")){System.out.println("here's the money");}elseif(reqStr.equals("time")){System.out.println("you have so much time");}client.close();server.close();}}
服務(wù)端控制臺:
Client
/**
* 客戶端
*
* @author Cushier
*
*/publicclassClient{publicstaticvoidmain(String[]args)throwsIOException{// 通過系統(tǒng)默認(rèn)類型的 SocketImpl 創(chuàng)建未連接套接字Socket socket=newSocket();// 此類實(shí)現(xiàn) IP 套接字地址(IP 地址 + 端口號)。它還可以是一個(gè)對(主機(jī)名 + 端口號),在此情況下,將嘗試解析主機(jī)名SocketAddress address=newInetSocketAddress("localhost",8898);// 將此套接字連接到服務(wù)器,并指定一個(gè)超時(shí)值?;蛘卟恢付ǔ瑫r(shí)時(shí)間socket.connect(address,1000);OutputStream os=socket.getOutputStream();os.write("money".getBytes());os.flush();// 接收響應(yīng),顯示結(jié)果InputStream is=socket.getInputStream();byte[]result=newbyte[1024];intlen=is.read(result);String resultStr=newString(result,0,len);System.out.println(resultStr);socket.close();}}
Server
/**
* 服務(wù)端
* @author Cushier
*
*/publicclassServer2{publicstaticvoidmain(String[]args)throwsIOException{// 創(chuàng)建綁定到特定端口的服務(wù)器套接字。ServerSocket server=newServerSocket(8898);// Socket accept() 偵聽并接受到此套接字的連接。Socket client=server.accept();System.out.println("接收到連接");InputStream is=client.getInputStream();BufferedInputStream bis=newBufferedInputStream(is);byte[]req=newbyte[1024];// 接收客戶端請求intlen=bis.read(req);String reqStr=newString(req,0,len);System.out.println(reqStr);// 將接收到的請求封裝成對象,傳送給請求的類MyRequest request=newMyRequest();MyResponse response=newMyResponse();OutputStream os=client.getOutputStream();if(reqStr.equals("money")){// 根據(jù)請求的信息,構(gòu)造處理的類MyServlet s1=newServletMoney();s1.service(request,response);// 通過client的響應(yīng),將結(jié)果響應(yīng)回客戶端os.write("here's the money".getBytes());os.flush();}elseif(reqStr.equals("time")){// 根據(jù)請求的信息,構(gòu)造處理的類MyServlet s2=newServletTime();s2.service(request,response);// 通過client的響應(yīng),將結(jié)果響應(yīng)回客戶端os.write("you have somuch time".getBytes());os.flush();}client.close();server.close();}}/*
* 我是一個(gè)有要求的人,你請求的這個(gè)資源必須是滿足我要求格式的類,作用:防止混亂,方便調(diào)用 這是我的標(biāo)準(zhǔn)
*/interfaceMyServlet{voidservice(MyRequest req,MyResponse resp);}classServletMoneyimplementsMyServlet{@Overridepublicvoidservice(MyRequest req,MyResponse resp){// 做出力所能及的處理}}classServletTimeimplementsMyServlet{@Overridepublicvoidservice(MyRequest req,MyResponse resp){// 做出力所能及的處理}}/*
* 請求信息都按規(guī)律封裝在該對象
*/classMyRequest{}classMyResponse{}
服務(wù)端控制臺:[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-MtJ94etz-1606099359234)(https://raw.githubusercontent.com/Cushier/picture/master/20190307152218.png)] 客戶端控制臺:
隨著客戶需求越來越復(fù)雜,需要的功能越來越多,我們的服務(wù)器端需要處理的請求越來越多,需要區(qū)分不同的請求,還需要按照不同請求進(jìn)行請求數(shù)據(jù)的提取以及資源的分配和運(yùn)算還有邏輯的處理,最后還需要響應(yīng)給客戶端,這就使得服務(wù)器端代碼越來越復(fù)雜,實(shí)現(xiàn)越來越困難。
??根據(jù)以往的經(jīng)驗(yàn),雙方進(jìn)行通信只需要遵循一定的規(guī)則就可以很明確地知道各部分?jǐn)?shù)據(jù)的含義,于是出現(xiàn)了網(wǎng)絡(luò)更上層的應(yīng)用協(xié)議(后面講的 HTTP 協(xié)議),規(guī)定服務(wù)器端和客戶端通信的規(guī)則。
客戶端請求服務(wù)器端和服務(wù)器端響應(yīng)客戶端,都按照固定的規(guī)則,那么接收請求和響應(yīng)數(shù)據(jù)這部分操作就可以固定下來,交給特定的一段代碼來執(zhí)行,從而減少服務(wù)器端的代碼量,于是出現(xiàn)了接下來說的服務(wù)器。
當(dāng)客戶端請求的資源越來越豐富,需求越來越復(fù)雜,程序的核心就應(yīng)該放在解決業(yè)務(wù)和計(jì)算響應(yīng)數(shù)據(jù)上,于是出現(xiàn)了服務(wù)器統(tǒng)一接收客戶端數(shù)據(jù)進(jìn)行處理并分發(fā)到不同的資源,由各個(gè)資源進(jìn)行處理,最后結(jié)果交由服務(wù)器響應(yīng)。
??從上面的描述可以發(fā)現(xiàn),現(xiàn)在所說的服務(wù)器只是負(fù)責(zé)接收請求,對請求進(jìn)行分發(fā),以及最后將獲取的數(shù)據(jù)進(jìn)行相應(yīng)的固定框架,至于數(shù)據(jù)怎么計(jì)算得出還得根據(jù)具體的業(yè)務(wù)需求編寫(填充)代碼。在沒有業(yè)務(wù)需求的情況下就能將服務(wù)器準(zhǔn)備出來,現(xiàn)在市面上的服務(wù)器有很多,比較常用的有:Tomcat、JBOOS、IBM 的 WebSphere、BEA的 WebLogic 以及 Apache 等。