客戶端請求服務器端通信, Web 編程發展基礎|樂字節

樂字節的小夥伴們,好久不見,甚是想念啊!

前面我發佈的文章算是把Java初級基礎階段講完了,接下來小樂將會給大家接着講Java中級階段——Javaweb。

首先,我們要看看Javaweb階段主要重點掌握的知識:

瞭解C/S和B/S兩種結構模式
理解Web應用程序的工作原理
實現第一個Servlet程序
理解程序的內部工作流程
掌握web.xml的基本配置
這篇文章我們先學習web發展基礎。

1、 簡單通信

回顧 Socket 編程給我們最大的感受,是可以在多臺電腦之間進行數據的傳輸,這就是網絡編程的開端和基礎,通過客戶端請求服務器端通信,直觀瞭解 Web 編程。

Server
`/**

  • 服務器端,接收客戶端請求並給出簡單的響應
  • @author Administrator

*/
public class Server {

public static void main(String[] args) throws IOException {
    //1、創建服務器,指定端口ServerSocket(int port)
    ServerSocket socket=new ServerSocket(8888);
    //2、接收客戶端連接
    Socket client=socket.accept();
    System.out.println("******************");
    //獲取數據的輸入流
    InputStream is=client.getInputStream();
    //使用字符緩存流
    BufferedReader br=new BufferedReader(new InputStreamReader(is));
    String msg="";
    while((msg=br.readLine())!=null){
        System.out.println(msg);
    }
    br.close();
}

}
樂字節原創`

Client
`/**

  • 客戶端:向服務器發送請求,併發送簡單的消息
  • @author Administrator

*/
public class Client {

public static void main(String[] args) throws UnknownHostException, IOException {
    //創建客戶端     必須指定服務器+端口    
    Socket client=new Socket("localhost",8888);
    //發送消息    請求資源
    //獲取發送流
    OutputStream os=client.getOutputStream();
    BufferedWriter br=new BufferedWriter(new OutputStreamWriter(os));
    //寫出消息,發送內容
    String msg="hello I need some source";
    br.write(msg);
    br.close();
}

}`

從上面的例子總結通信條件如下:

1)、需要有服務器端(server) :等待被請求,需要暴露ip 和 port

2)、需要有客戶端(client):主動發起請求 ,知曉服務端的ip 和 port

3)、通信規則(協議):TCP/IP協議

ip用於定位計算機;端口號(定位程序),用於標識進程的邏輯地址,不同進程的標誌;有效端口:0~65535,其中0~1024由系統使用或者保留端口,開發中建議使用1024以上的端口。

2. 不同請求

Client
`package com.shsxt.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
/**

  • @author Lj

*

  • 客戶端

*/
public class Client {

public static void main(String[] args) throws IOException {
    //  通過系統默認類型的 SocketImpl 創建未連接套接字
    Socket socket = new Socket();
    //此類實現 IP 套接字地址(IP 地址 + 端口號)。它還可以是一個對(主機名 + 端口號),在此情況下,將嘗試解析主機名
    SocketAddress address = new InetSocketAddress("localhost",8898);
    // 將此套接字連接到服務器,並指定一個超時值。  或者不指定超時時間   
    socket.connect(address, 1000);
    OutputStream os = socket.getOutputStream();
    os.write("time".getBytes());
    os.flush();
    socket.close();
}

}`

Server
`package com.shsxt.socket;

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

/**

  • @author Lj
  • 服務端
  • public class ServerSocketextends Object:此類實現服務器套接字。服務器套接字等待請求通過網絡傳入。它基於該請求執行某些操作,然後可能向請求者返回結果。

*/
public class Server {

public static void main(String[] args) throws IOException {
    //創建綁定到特定端口的服務器套接字。
    ServerSocket server = new ServerSocket(8898);
    
    // Socket accept()   偵聽並接受到此套接字的連接。 
    Socket client = server.accept();    
    System.out.println("接收到連接");
    
    InputStream is = client.getInputStream();
    BufferedInputStream bis = new BufferedInputStream(is);
    byte[] req = new byte[1024];
    // 接收客戶端請求
    int len = bis.read(req);
    String reqStr = new String(req,0,len);
    System.out.println(reqStr);
    if(reqStr.equals("money")){
        System.out.println("here's the money");
    }else if(reqStr.equals("time")){
        System.out.println("you have so much time");
    }    
    client.close();
    server.close();
}

}`

3. 複雜請求

Client
``package com.shsxt.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
/**

  • @author Lj
  • 客戶端

*/
public class Client {

public static void main(String[] args) throws IOException {
    //  通過系統默認類型的 SocketImpl 創建未連接套接字
    Socket socket = new Socket();
    //此類實現 IP 套接字地址(IP 地址 + 端口號)。它還可以是一個對(主機名 + 端口號),在此情況下,將嘗試解析主機名
    SocketAddress address = new InetSocketAddress("localhost",8898);
    // 將此套接字連接到服務器,並指定一個超時值。  或者不指定超時時間   
    socket.connect(address, 1000);
    
    OutputStream os = socket.getOutputStream();
    os.write("money".getBytes());
    os.flush();        
    // 接收響應, 顯示結果
    InputStream is = socket.getInputStream();
    byte[] result = new byte[1024];
    int len = is.read(result);
    String resultStr  = new String(result,0,len);
    System.out.println(resultStr);
    socket.close();
}

}`

Server

package com.shsxt.socket;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**

  • @author Lj 服務端 public class ServerSocketextends
  • Object:此類實現服務器套接字。服務器套接字等待請求通過網絡傳入。它基於該請求執行某些操作,然後可能向請求者返回結果。

*/
public class Server {

public static void main(String[] args) throws IOException {
    // 創建綁定到特定端口的服務器套接字。
    ServerSocket server = new ServerSocket(8898);

    // Socket accept() 偵聽並接受到此套接字的連接。
    Socket client = server.accept();
    System.out.println("接收到連接");
    InputStream is = client.getInputStream();
    BufferedInputStream bis = new BufferedInputStream(is);
    byte[] req = new byte[1024];
    // 接收客戶端請求
    int len = bis.read(req);
    String reqStr = new String(req, 0, len);
    System.out.println(reqStr);
    // 將接收到的請求封裝成對象, 傳送給請求的類
    MyRequest request = new MyRequest();
    MyResponse response = new MyResponse();

    OutputStream os = client.getOutputStream();
    if (reqStr.equals("money")) {
        // 根據請求的信息, 構造處理的類
        MyServlet s1 = new ServletMoney();
        s1.service(request, response);
        // 通過client的響應, 將結果響應回客戶端
        os.write("here's the money".getBytes());
        os.flush();
    } else if (reqStr.equals("time")) {
        // 根據請求的信息, 構造處理的類
        MyServlet s2 = new ServletTime();
        s2.service(request, response);
        // 通過client的響應, 將結果響應回客戶端
        os.write("you have somuch time".getBytes());
        os.flush();
    }
    client.close();
    server.close();
}

}
/*

  • 我是一個有要求的人, 你請求的這個資源必須是滿足我要求格式的類 作用:防止混亂,方便調用
  • 這是我的標準

*/
interface MyServlet {

void service(MyRequest req, MyResponse resp);

}
class ServletMoney implements MyServlet {

/*
 * @see com.shsxt.socket.MyServlet#service(com.shsxt.socket.MyRequest)
 */
@Override
public void service(MyRequest req, MyResponse resp) {
    // 做出力所能及的處理
}

}
class ServletTime implements MyServlet {

/*
 * @see com.shsxt.socket.MyServlet#service(com.shsxt.socket.MyRequest)
 */
@Override
public void service(MyRequest req, MyResponse resp) {
    // 做出力所能及的處理
}

}
/*

  • 請求信息都按規律封裝在該對象

*/
class MyRequest {
}
class MyResponse {
}`

隨着客戶需求越來越複雜,需要的功能越來越多,我們的服務器端需要處理的請求越來越多,需要區分不同的請求,還需要按照不同請求進行請求數據的提取以及資源的分配和運算還有邏輯的處理,最後還需要響應給客戶端,這就使得服務器端代碼越來越複雜,實現越來越困難。

根據以往的經驗,雙方進行通信只需要遵循一定的規則就可以很明確地知道各部分數據的含義,於是出現了網絡更上層的應用協議(後面講的 HTTP 協議),規定服務器端和客戶端通信的規則。

客戶端請求服務器端和服務器端響應客戶端,都按照固定的規則,那麼接收請求和相應數據這部分操作就可以固定下來,交給特定的一段代碼來執行,從而減少服務器端的代碼量,於是出現了接下來說的服務器。

4. 服務器的出現

當客戶端請求的資源越來越豐富,需求越來越複雜,程序的核心就應該放在解決業務和 計算響應數據上,於是出現了服務器統一接收客戶端處理並進行分發到不同的資源,由各個資源進行處理,最後結果交由服務器響應。

從上面的描述可以發現,現在所說的服務器只是負責接收請求,對請求進行分發,以及最後將獲取的數據進行相應的固定框架,至於數據怎麼計算得出還得根據具體的業務需求編 寫(填充)代碼。在沒有業務需求的情況下就能將服務器準備出來,現在市面上的服務器有 很多,比較常用的有:Tomcat、JBOOS、IBM 的 WebSphere、BEA 的 WebLogic 以及 Apache 等。

好了,web發展基礎就講到這裏了,下一文章將會給大家Javaweb的介紹和C/S、B/S體系結構,敬請關注樂字節哦~~~~

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