利用Java實現Web服務器
一、HTTP協議的作用原理
HTTP協議的工作原理包括四個步驟:
1.連接:Web瀏覽器與Web服務器建立連接。
2.請求:Web瀏覽器通過socket向Web服務器提交請求。
3.應答:Web瀏覽器提交請求后,通過HTTP傳送給Web服務器。Web服務器接到請求后,進行事務處理,處理結果又通過HTTP傳回給Web瀏覽器,從而在Web瀏覽器上顯示出所請求的頁面。
4.關系連接:當應答結束后,Web瀏覽器與Web服務器必須斷開,以保證其它Web瀏覽器能夠與Web服務器建立連接。
二、用Java實現Web服務器的程序設計
根據上述HTTP協議的作用原理,實現GET請求的Web服務器程序的方法如下:
1.創建ServerSocket類對象,監聽端口8080。這是為了區別于HTTP的標準TCP/IP端口80而取的;2.等待、接受客戶機連接到端口8080,得到與客戶機連接的socket;3.創建與socket關聯的輸入流instream和輸入出流outstream;
格式為:GET路徑/文件名HTTP/1.0;4.從與socket關聯的輸入流instream中讀取一行客戶機提交的請求信息,請求信息的格式為:GET路徑/文件名HTTP/1.0;5.從請求信息中獲取請求類型。如果請求類型是GET,則從請求信息中獲取所訪問的HTML文件名。沒有HTML文件名時,則以index.htm1作為文件名;6.如果HTML文件存在,則打開HTML文件,把HTTP頭信息和HTML文件內容通過socket傳回給Web服務器,然后關閉文件,否則發送錯誤信息給Web瀏覽器;7.關閉與相應Web瀏覽器連接的socket字。
下面的程序是根據上述方法編寫的,可實現多線程的Web服務器,以保證多個客戶機能同時與該Web服務器連接。
程序中的Connection Thread線程子類用來分析一個Web瀏覽器提交的請求,并將應答信息傳回給Web瀏覽器。其中,getrequest()方法用來檢測客戶的請求是否為"GET";getfilename(s)方法是從客戶請求信息s中獲取要訪問的HTML文件名;sendfile()方法把指定文件內容通過socket傳回給Web瀏覽器。
HTTP協議的工作原理包括四個步驟:
1.連接:Web瀏覽器與Web服務器建立連接。
2.請求:Web瀏覽器通過socket向Web服務器提交請求。
3.應答:Web瀏覽器提交請求后,通過HTTP傳送給Web服務器。Web服務器接到請求后,進行事務處理,處理結果又通過HTTP傳回給Web瀏覽器,從而在Web瀏覽器上顯示出所請求的頁面。
4.關系連接:當應答結束后,Web瀏覽器與Web服務器必須斷開,以保證其它Web瀏覽器能夠與Web服務器建立連接。
二、用Java實現Web服務器的程序設計
根據上述HTTP協議的作用原理,實現GET請求的Web服務器程序的方法如下:
1.創建ServerSocket類對象,監聽端口8080。這是為了區別于HTTP的標準TCP/IP端口80而取的;2.等待、接受客戶機連接到端口8080,得到與客戶機連接的socket;3.創建與socket關聯的輸入流instream和輸入出流outstream;
格式為:GET路徑/文件名HTTP/1.0;4.從與socket關聯的輸入流instream中讀取一行客戶機提交的請求信息,請求信息的格式為:GET路徑/文件名HTTP/1.0;5.從請求信息中獲取請求類型。如果請求類型是GET,則從請求信息中獲取所訪問的HTML文件名。沒有HTML文件名時,則以index.htm1作為文件名;6.如果HTML文件存在,則打開HTML文件,把HTTP頭信息和HTML文件內容通過socket傳回給Web服務器,然后關閉文件,否則發送錯誤信息給Web瀏覽器;7.關閉與相應Web瀏覽器連接的socket字。
下面的程序是根據上述方法編寫的,可實現多線程的Web服務器,以保證多個客戶機能同時與該Web服務器連接。
| //WebServer.java用Java編寫Web服務器 import java.io.*; import java.net.*; import java.util.Date; public class WebServer{ public static void main(String args[]) { int i=1,PORT=8080; ServerSocket server=null; Socketclient=null; try{ server=new ServerSocket(PORT); System.out.println("Web Server is listening on port" +server.getLocalPort()); for(;;){ client=server.accept(); //接受客戶機的連接請求 new Connection Thread(client,i).start(); i++; } }catch(Exception e){System.out.println(e);} } } /*Connnection Thread類完成 與一個Web瀏覽器的通信*/ class Connection Thread extends Thread{ Socket client;//連接Web瀏覽器的socket字 int counter;//計數器 public Connection Thread(Socketcl,int c){ client=cl; counter=c; } public void run()//線程體 { try{ String deskIP=client.getInetAddress().toString(); //客戶機IP地址 int destport=client.getPort(); //客戶機端口號 System.out.println ("Connecction"+counter+": connected to "+destIP+"on port"+destport+"."); PrintStream outstream=new printStream(client.getOoutputStream()); DataInputStreaminstream+new DataInputStream(client.getInputStream()); String inline=instream.readLine(); //讀取Web瀏覽器提交的請求信息 System.out.println("Received:"+inline); if(getrequest(inline)){//如果是GET請求 String filename=getfilename(inline); File file=new File (filename); if(file.exists()){ //若文件存在,則將文件送給Web瀏覽器 System.out.println(filename+"requested."); outstream.println("HTTP/1.0200OK"); outstream.println("MIME_version:1.0"); outstream.println("Content_Type:text/htm1"); int len=(int)file.length(); outstream.println("Content_Length:"+len); outstream.println(""); sendfile(outstream,file);//發送文件 outstream.flush(); }else{//文件不存在時 String notfound="<html><head><title> Not Found</title></head> <body><hl>Error404-File notfound </hl></body></html>"; outstream.println("HTTP /1.0 404 no found"); outstream.println("Content_Type:text /html"); outstream.println("Content_Length:" +notfound.length() +2); outstream.println(""); outstream.println(notfound); outstream.flush(); } } long m1=1; while(m10) { if(s.substring(0,3).equalsIgnoreCase("GET"))return true; } return false; } /*獲取要訪問的文件名*/ String getfilename(String s){ String f=s.substring(s.indexOf('')+1); f=f.substring(0,f.indexOf('')); try{ if(f.charAt(0)=='/') f=f.substring(1); }catch(String IndexOutOfBoundsException e){ System.out.println("Exception:"+e); } if(f.equals(""))f="index.html"; return f; } /*把指定文件發送給Web瀏覽器*/ void sendfile(PrintStream outs,File file){ try{ DataInputStreamin=new DataInputStream(new FileInputStream(file)); int len=(int)file.length(); byte buf[]=new byte[len]; in.readFully(buf); outs.write(buf,0,len); outs.flush(); in.close(); }catch(Exception e){ System.out.println("Error retrieving file."); System.exit(1); } } } |
程序中的Connection Thread線程子類用來分析一個Web瀏覽器提交的請求,并將應答信息傳回給Web瀏覽器。其中,getrequest()方法用來檢測客戶的請求是否為"GET";getfilename(s)方法是從客戶請求信息s中獲取要訪問的HTML文件名;sendfile()方法把指定文件內容通過socket傳回給Web瀏覽器。