熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

如何用Java實現Web服務器

2022-06-13   來源: Java核心技術 

  HTTP協議的作用原理

  WWW是以Internet作為傳輸媒介的一個應用系統WWW網上最基本的傳輸單位是Web網頁WWW的工作基於客戶機/服務器計算模型由Web 浏覽器(客戶機)和Web服務器(服務器)構成兩者之間采用超文本傳送協議(HTTP)進行通信HTTP協議是基於TCP/IP協議之上的協議是Web浏覽器和Web服務器之間的應用層協議是通用的無狀態的面向對象的協議HTTP協議的作用原理包括四個步驟

  () 連接Web浏覽器與Web服務器建立連接打開一個稱為socket(套接字)的虛擬文件此文件的建立標志著連接建立成功

  () 請求Web浏覽器通過socket向Web服務器提交請求HTTP的請求一般是GET或POST命令(POST用於FORM參數的傳遞)GET命令的格式為

  GET 路徑/文件名 HTTP/

  文件名指出所訪問的文件HTTP/指出Web浏覽器使用的HTTP版本

  () 應答Web浏覽器提交請求後通過HTTP協議傳送給Web服務器Web服務器接到後進行事務處理處理結果又通過HTTP傳回給Web浏覽器從而在Web浏覽器上顯示出所請求的頁面

  例假設客戶機與/mydir/l建立了連接就會發送GET命令GET /mydir/l HTTP/主機名為的Web服務器從它的文檔空間中搜索子目錄mydir的文件l如果找到該文件Web服務器把該文件內容傳送給相應的Web浏覽器

  為了告知 Web浏覽器傳送內容的類型Web服務器首先傳送一些HTTP頭信息然後傳送具體內容(即HTTP體信息)HTTP頭信息和HTTP體信息之間用一個空行分開

  常用的HTTP頭信息有

  ① HTTP OK

  這是Web服務器應答的第一行列出服務器正在運行的HTTP版本號和應答代碼代碼 OK表示請求完成

  ② MIME_Version

  它指示MIME類型的版本

  ③ content_type類型

  這個頭信息非常重要它指示HTTP體信息的MIME類型content_typetext/html指示傳送的數據是HTML文檔

  ④ content_length長度值

  它指示HTTP體信息的長度(字節)

  () 關閉連接當應答結束後Web浏覽器與Web服務器必須斷開以保證其它Web浏覽器能夠與Web服務器建立連接

  Java實現Web服務器功能的程序設計

  根據上述HTTP協議的作用原理實現GET請求的Web服務器程序的方法如下

  () 創建ServerSocket類對象監聽端口這是為了區別於HTTP的標准TCP/IP端口而取的

  () 等待接受客戶機連接到端口得到與客戶機連接的socket

  () 創建與socket字相關聯的輸入流instream和輸出流outstream

  () 從與socket關聯的輸入流instream中讀取一行客戶機提交的請求信息請求信息的格式為GET 路徑/文件名 HTTP/

  () 從請求信息中獲取請求類型如果請求類型是GET則從請求信息中獲取所訪問的HTML文件名沒有HTML文件名時則以l作為文件名

  () 如果HTML文件存在則打開HTML文件把HTTP頭信息和HTML文件內容通過socket傳回給Web浏覽器然後關閉文件否則發送錯誤信息給Web浏覽器

  () 關閉與相應Web浏覽器連接的socket字

  下面的程序是根據上述方法編寫的可實現多線程的Web服務器以保證多個客戶機能同時與該Web服務器連接

  程序WebServerjava文件

  //WebServerjava 用JAVA編寫Web服務器

  import javaio*

  import *

  public class WebServer {

  public static void main(String args[]) {

  int i= PORT=

  ServerSocket server=null

  Socket client=null

  try {

  server=new ServerSocket(PORT)

  Systemoutprintln(Web Server is listening on port +servergetLocalPort())

  for () {client=serveraccept() //接受客戶機的連接請求

  new ConnectionThread(clienti)start()

  i++

  }

  } catch (Exception e) {Systemoutprintln(e)}

  }

  }

  /* ConnnectionThread類完成與一個Web浏覽器的通信 */

  class ConnectionThread extends Thread {

  Socket client //連接Web浏覽器的socket字

  int counter //計數器

  public ConnectionThread(Socket clint c) {

  client=cl

  counter=c

  }

  public void run() //線程體

  {try {

  String destIP=clientgetInetAddress()toString() //客戶機IP地址

  int destport=clientgetPort() //客戶機端口號

  Systemoutprintln(Connection +counter+connected to +destIP+ on port +destport+

  PrintStream outstream=new PrintStream(clientgetOutputStream())

  DataInputStream instream=new DataInputStream(clientgetInputStream())

  String inline=instreamreadLine() //讀取Web浏覽器提交的請求信息

  Systemoutprintln(Received+inline)

  if (getrequest(inline)) { //如果是GET請求

  String filename=getfilename(inline)

  File file=new File(filename)

  if (fileexists()) { //若文件存在則將文件送給Web浏覽器

  Systemoutprintln(filename+ requested

  outstreamprintln(HTTP/ OK

  outstreamprintln(MIME_version

  outstreamprintln(Content_Typetext/html

  int len=(int)filelength()

  outstreamprintln(Content_Length+len)

  outstreamprintln(

  sendfile(outstreamfile) //發送文件

  outstreamflush()

  } else { //文件不存在時

  String notfound=

  

Error file not found

  outstreamprintln(HTTP/ no found

  outstreamprintln(Content_Typetext/html

  outstreamprintln(Content_Length+notfoundlength()+

  outstreamprintln(

  outstreamprintln(notfound)

  outstreamflush()

  }

  }

  long m=

  while (m<) {m++} //延時

  clientclose()

  } catch (IOException e) {

  Systemoutprintln(Exception+e)

  }

  }

  /* 獲取請求類型是否為GET */

  boolean getrequest(String s) {

  if (slength()>

  {if (ssubstring(equalsIgnoreCase(GET)) return true

  }

  return false

  }

  /* 獲取要訪問的文件名 */

  String getfilename(String s) {

  String f=ssubstring(sindexOf(′ ′)+

  f=fsubstring(findexOf(′ ′))

  try {

  if (fcharAt()==′/′)

  f=fsubstring(

  } catch (StringIndexOutOfBoundsException e) {

  Systemoutprintln(Exception+e)

  }

  if (fequals()) f=l

  return f

  }

  /*把指定文件發送給Web浏覽器 */

  void sendfile(PrintStream outsFile file) {

  try {

  DataInputStream in=new DataInputStream(new FileInputStream(file))

  int len=(int)filelength()

  byte buf[]=new byte[len]

  inreadFully(buf)

  outswrite(buflen)

  outsflush()

  inclose()

  } catch (Exception e) {

  Systemoutprintln(Error retrieving file

  Systemexit(

  }

  }

  }

  程序中的ConnectionThread線程子類用來分析一個Web浏覽器提交的請求並將應答信息傳回給Web浏覽器其中getrequest()方法用來檢測客戶的請求是否為GETgetfilename(s)方法是從客戶請求信息s中獲取要訪問的HTML文件名sendfile()方法把指定文件內容通過socket傳回給Web浏覽器

  對上述程序的getrequest()方法和相關部分作修改也能對POST請求進行處理

  運行實例

  為了測試上述程序的正確性將編譯後的WebServerclassConnectionThreadclass和下面的l文件置於網絡的某台主機的同一目錄中(如主機NTSRV的CJWEB目錄)

  程序l文件

  

  

  

  

  

  

  

這是用JAVA寫出的WEB服務器主頁

  

  


  

  

  首先在該主機上用java命令運行WebServerclass

  Cjweb>java webserver

  然後在客戶機運行浏覽器軟件在URL處輸入WebServer程序所屬的URL地址(如就在浏覽器窗口顯示出指定的HTML文檔

  注意不能缺省端口號如缺省則運行該主機的正常WEB服務器

  說明不具備網絡條件的可在安裝了Windows 的單機上進行測試方法是用localhost或代替URL地址的域名部分即URL地址為


From:http://tw.wingwit.com/Article/program/Java/hx/201311/26626.html
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.