java多线程web服务器实现
原理说明:
HTTP协议的作用原理包括四个步骤:
(1)连接:Web浏览器与Web服务器建立连接,打梯瓣氨割开一个称为socket(套接字)的虚拟文件,此文件的建立标志着连接建立成功。
(2)请求:Web浏览器通过socket向Web服务器提交请求。HTTP的请求一般是GET或POST命令(POST用于FORM参数的传递)。GET命
令的格式为:GET路径/文件名HTTP/1.0文件名指出所访问的文件,HTTP/1.0指出Web浏览器使用的HTTP版本。
(3)应答:Web浏览器提交请求后,通过HTTP协议传送给Web服务器。Web服务器接到后,进行事务处理,处理结果又通过HTTP传
回给Web浏览器,从而在Web浏览器上显示出所请求的页面。
Java实现Web服务器功能的程序设计
根据上述HTTP协议的作用原理,实现GET请求的Web服务器程序的方法如下:
(1)创建ServerSocket类对象,监听端口5000。这是为了区别于HTTP的标准TCP/IP端口80而取的;
(2)等待、接受客户机连接到端口5000,得到与客户机连接的socket;
(3)创建与socket字相关联的输入流instream和输出流outstream;
(4)从与socket关联的输入流instream中读取一行客户机提交的请求信息,请求信息的格式为:GET路径/文件名HTTP/1.0
(5)从请求信息中获取请求类型。如果请求类型是GET,则从请求信息中获取所访问的HTML文件名。没有HTML文件名时,则以index.html作为文件名;
(6)如果HTML文件存在,则打开HTML文件,把HTTP头信息和HTML文件内容通过socket传回给Web浏览器,然后关闭文件。否则发送错误信息给Web浏览器;
(7)关闭与相应Web浏浏览器连接的socket字。
一 首先打开开发工具Eclipse
Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。
向Eclipse中输入如下Web服务器程序源码
import java.io.*;
import java.net.*;
public class webs{
@SuppressWarnings("deprecation")
public static void main(String args[]) {
int i=1, PORT=5000;
ServerSocket server=null;
Socket client=null;
try{
server=new ServerSocket(PORT);
System.out.println("Web Server is listening on port "+server.getLocalPort());
for (;;) {
client=server.accept(); // 接受客户机的连接请求
new ConnectionThread(client,i).start();
i++;
}
}catch(Exception e) {System.out.println(e);}
}
}
/* ConnnectionThread类完成与一个Web浏览器的通信 */
class ConnectionThread extends Thread {
public Socket client; // 连接Web浏览器的socket字
public int counter; // 计数器
public ConnectionThread(Socket cl,int c) {
client=cl;
counter=c;
}
@SuppressWarnings("deprecation")
public void run() // 线程体
{//BufferedReader instream=null;
//PrintWriter outstream=null;
try{
String destIP=client.getInetAddress().toString(); // 客户机IP地址
int destport=client.getPort(); // 客户机端口号
System.out.println("Connection "+counter+":connected to "+destIP+" on port "+destport+".");
PrintStream outstream=new PrintStream(client.getOutputStream());
//outstream = new PrintWriter(client.getOutputStream(), true);
DataInputStream instream=new DataInputStream(client.getInputStream());
//instream = new BufferedReader(new InputStreamReader(client.getInputStream()));
@SuppressWarnings("deprecation")
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.0 200 OK");
outstream.println("MIME_version:1.0");
outstream.println("Content_Type:text/html");
int len=(int)file.length();
outstream.println("Content_Length:"+len);
outstream.println("");
sendfile(outstream,file); // 发送文件
outstream.flush();
}
else { // 文件不存在时
String filenam="error.html";
File file1=new File(filenam);
System.out.println(filename+" requested.");
outstream.println("HTTP/1.0 200 OK");
outstream.println("MIME_version:1.0");
outstream.println("Content_Type:text/html");
int len=(int)file.length();
outstream.println("Content_Length:"+len);
outstream.println("");
sendfile(outstream,file1); // 发送文件
outstream.flush();
}
}
long m1=1;
while (m1<11100000)
{m1++;} // 延时
client.close();
}catch(IOException e) {
System.out.println("Exception:"+e);
}
}
/* 获取请求类型是否为“GET” */
boolean getrequest(String s) {
if (s.length()>0)
{
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(StringIndexOutOfBoundsException e) {
System.out.println("Exception:"+e);
}
if (f.equals("")) f="index.html";
return f;
}
/*把指定文件发送给Web浏览器 */
void sendfile(PrintStream outs,File file){
try{
DataInputStream in=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);}
}
}
在Eclipse中如下图:
二 为了测试上述程序的正确性,将编译后的webs.class、ConnectionThread.class和下面的index.html文件置于本机的同一目录中在dos里运行web服务器
三 然后在客户机运行浏览器软件,在URL处输入web程序所属的URL地址(如:http://172.16.27.90:5000/index.html)或(如:http://172.16.27.90:5000/),就在浏览器窗口显示出指定的HTML文档。
注意,不能缺省端口号8080,如缺省,则运行该主机的正常WEB服务器。
1.单一browser请求
dos屏中收到的文本信息为:
D:\eclips\shi\bin>java webs
Web Server is listening on port 5000
Connection 1:connected to /172.16.27.90 onport 4592.
Received:GET /index.html HTTP/1.1
index.html requested.
Connection 2:connected to /172.16.27.90 onport 4593.
Received:GET /tab.css HTTP/1.1
tab.css requested.
Connection 3:connected to /172.16.27.90 onport 4594.
Received:GET /images/fly.gif HTTP/1.1
images/fly.gif requested.
Connection 4:connected to /172.16.27.90 onport 4595.
Received:GET /images/background.jpg HTTP/1.1
images/background.jpg requested.
Connection 5:connected to /172.16.27.90 onport 4596.
Received:GET /images/main-bg.jpg HTTP/1.1
images/main-bg.jpg requested.
Connection 6:connected to /172.16.27.90 onport 4597.
Received:GET /images/bann.jpg HTTP/1.1
images/bann.jpg requested.
Connection 7:connected to /172.16.27.90 onport 4598.
Received:GET /images/07.gif HTTP/1.1
images/07.gif requested.
Connection 8:connected to /172.16.27.90 onport 4599.
Received:GET/?ú????-??????×?(???°??±???°????·???ú).wma HTTP/1.1
Connection 9:connected to /172.16.27.90 onport 4600.
Received:GET/%E8%83%A1%E6%B8%85%E8%93%9D-%E4%B8%8E%E8%B0%81%E5%90%8C%E5%9D%90(%
E7%94%B5%E5%BD%B1%E3%80%8A%E4%BF%9D%E6%8C%81%E7%88%B1%E4%BD%A0%E3%80%8B%E6%8F%92
%E6%9B%B2).wma HTTP/1.1(个人网站中的wma文件)
2.多browser并发通信同时发出三次请求实现多线程通信
如下两图所示:
实现多线程通信的dos屏中收到的文本信息:
D:\eclips\shi\bin>java webs
Web Server is listening on port 5000
Connection 1:connected to /172.16.27.90 onport 4592.
Received:GET /index.html HTTP/1.1
index.html requested.
Connection 2:connected to /172.16.27.90 onport 4593.
Received:GET /tab.css HTTP/1.1
tab.css requested.
…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………
Connection 31:connected to /172.16.27.90 onport 4658.
Received:GET /images/fly.gif HTTP/1.1
Connection 33:connected to /172.16.27.90 onport 4660.
images/fly.gif requested.
Received:GET /images/main-bg.jpg HTTP/1.1
images/main-bg.jpg requested.
Connection 32:connected to /172.16.27.90 onport 4659.
Received:GET /images/background.jpg HTTP/1.1
Connection 45:connected to /172.16.27.90 onport 4672.
Connection 44:connected to /172.16.27.90 onport 4671.
Connection 42:connected to /172.16.27.90 onport 4669.
Received:GET /images/07.gif HTTP/1.1
images/07.gif requested.
Connection 46:connected to /172.16.27.90 onport 4673.
Received:GET/%E8%83%A1%E6%B8%85%E8%93%9D-%E4%B8%8E%E8%B0%81%E5%90%8C%E5%9D%90(%
E7%94%B5%E5%BD%B1%E3%80%8A%E4%BF%9D%E6%8C%81%E7%88%B1%E4%BD%A0%E3%80%8B%E6%8F%92
%E6%9B%B2).wma HTTP/1.1
3.如果文件请求不存在文件如a.txt
Java实现的web服务器完成了,希望给大家有所帮助!