自己动手编写web server(二)
来源:互联网 发布:清华大学软件学院考研 编辑:程序博客网 时间:2024/05/18 23:27
最近笔者有点忙啊,每天上班,晚上回来写毕业论文,没有太多空闲时间来学东西了。上一篇文章写完,自己读了几遍,感觉笔者的表达能力和文字功底确实垃圾,高考语文也就值103分,没有遗憾!!!
笔者有个习惯,就是遇到不会的东西总爱网上搜一搜,然后看各种博客,最近也浏览了一些技术大牛的博客,他们的浏览量和回复超越笔者的博客几条街。。。。笔者决心要写出他们那样的博客!!
闲话扯多了,进入正题!!!
上一篇,简单描述了HTTP协议,以及我们的思路,接下来,我们详细地来实现这个server,首先我们认识一下Socket!!!
说实话,笔者对网络编程一直是望而却步,究其原因,就是这个Socket,各种书或者教材翻译成“套接字”,笔者当时第一次接触这个东西时,年幼无知、不了解翻译人员的意思、发散思维较差等等原因,一直无法理解“套接字”的翻译表达了什么意思!!!现在依然无法理解!!!
Socket
现在给大家讲一下笔者对Socket的理解:Socket就是两台电脑之间的连接。。。那么两台电脑如何连接?现实生活中,我们用网线、设置IP地址等等,那么Socket也一样,充当网线与IP的功能。使用Socket对象,我们要为他设置IP以及端口,Socket对象为我们提供了输入输出功能,就像网线,可以传输数据。
public Socket (java.lang.String host, int port)
上面是Socket的其中一个构造函数,第一个参数:要请求的服务器名称或者IP地址;第二个参数:服务器端的端口号。
一旦你成功创建了一个Socket对象,你就可以通过这个对象获得与服务器之间的输入输出流。如果你要发送字节给服务器,使用getOutputStream方法来获取一个java.io.OutputStream对象,这就是输出流;如果你要读取服务器发送给你的字节,使用getInputStream方法用来返回一个java.io.InputStream对象,这是输入流。java的读取流,可以参考我以前的blog:http://blog.csdn.net/zsmj_2011/article/details/7975661和http://blog.csdn.net/zsmj_2011/article/details/7977754
ServerSocket
public ServerSocket(int port, int backLog, InetAddress bindingAddress);
上面是ServerSocket的一个构造函数,第一参数:指定服务器端监听端口号;第二参数:指定服务器端处理请求队列的大小,第三个参数:指定监听的IP地址,一般是本机。
web server 设计
package com.la.webserver;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;public class WebServer {//设置静态资源的目录public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot";//设置关闭命令private static final String SHUTDOWN_COMMAND="/SHUTDOWN";private boolean shutdown=false;public static void main(String[] args) {WebServer server=new WebServer();server.await();}public void await() {ServerSocket serverSocket=null;//监听8080端口int port=8080;try {serverSocket=new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));} catch (IOException e) {e.printStackTrace();System.exit(1);}//循环等待客户端连接while (!shutdown) {Socket socket=null;InputStream inputStream=null;OutputStream outputStream=null;try {socket=serverSocket.accept();//当有客户端连接时inputStream=socket.getInputStream();//获取请求字符流outputStream=socket.getOutputStream();//输出流//处理客户端请求---RequestRequest request=new Request(inputStream);request.parse();//向客户端发送ResponseResponse response=new Response(outputStream);response.setRequest(request);response.sendStaticResource();//关闭socketsocket.close();//检查如果是shutdown命令,关闭服务器shutdown=request.getUri().equals(SHUTDOWN_COMMAND);} catch (Exception e) {e.printStackTrace();continue;}}}}
package com.la.webserver;import java.io.IOException;import java.io.InputStream;public class Request {private InputStream inputStream;private String uri;public String getUri() {return uri;}public void setUri(String uri) {this.uri = uri;}public Request(InputStream inputStream) {this.inputStream=inputStream;}public void parse() {//从socket读取字符StringBuffer request=new StringBuffer(2048);int i;byte[] buffer=new byte[2048];try {i=inputStream.read(buffer);} catch (IOException e) {e.printStackTrace();i=-1;}for (int j = 0; j < i; j++) {request.append((char)buffer[j]);}System.out.println(request.toString());uri=parseUri(request.toString());}/** * 从客户端请求字符串中截取请求资源uri * @param requeString 请求字符串,包括请求头、请求方法、请求资源的uri * @return 请求资源的uri */private String parseUri(String requeString){int index1,index2;//比如GET /index.html HTTP/1.1//请求方法、请求资源、版本之间以空格隔开index1=requeString.indexOf(' ');if (index1!=-1) {index2=requeString.indexOf(' ', index1+1);if (index2>index1) {return requeString.substring(index1+1, index2);}}return null;}}
package com.la.webserver;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.OutputStream;public class Response {private static final int BUFFER_SIZE=1024;Request request;OutputStream outputStream;public Response(OutputStream outputStream) {this.outputStream=outputStream;}public void setRequest(Request request) {this.request=request;}//发送静态资源public void sendStaticResource() throws IOException {byte[] bytes=new byte[BUFFER_SIZE];FileInputStream fis=null;try {File file=new File(WebServer.WEB_ROOT, request.getUri());if (file.exists()) {//如果请求的静态资源文件存在fis=new FileInputStream(file);int ch=fis.read(bytes, 0, BUFFER_SIZE);while (ch!=-1) {outputStream.write(bytes, 0, ch);ch=fis.read(bytes, 0, BUFFER_SIZE);}}else {//如果静态资源不存在String errorMessage="HTTP/1.1 404 File Not Found\r\n"+"Content-Type:test/html\r\n"+"Content-Length:23\r\n"+"\r\n"+"<h1>File Not Found</h1>";outputStream.write(errorMessage.getBytes());}} catch (Exception e) {System.out.println(e.toString());}finally{if (fis!=null) {fis.close();}}}}
首先你的程序目录里要有个文件夹“webroot”,这个文件夹里要有你请求的静态资源,运行效果如下:
需要改进的地方
- 可以处理servlet、jsp;
- 使用多线程技术,优化服务器处理
- 使用NIO技术
- 自己动手编写web server(二)
- 自己动手编写web server(一)
- 自己动手编写tomcat服务器(二)
- 自己动手写php web server
- 自己动手编写Web服务工具[解析]
- 自己动手编写Web服务解析工具
- 自己动手编写Web服务工具[执行]
- 自己动手编写Web服务工具[执行]
- Web Server程序编写学习笔记(二)
- 自己动手做WEB控件(二)
- 自己动手开发一个 Web 服务器(二)
- 自己动手写操作系统二(编写内核Hello World 教程)
- web server服务程式编写
- 自己动手写web服务器二(处理get请求)
- 自己动手写Web容器之TomJetty之二:开启服务器
- 自己动手写一个web框架(二):实现AOP
- 自己动手编写 IronPython IDE
- 自己动手编写 IronPython IDE
- 【PSU升级】Oracle_RAC10.2.0.1到10.2.0.5.9的详细升级过程(三)
- iOS - 国际化(多语言):
- NSDateFormatter显示格式总结
- Eclipse快捷键大全
- WPF应用程序如何重启当前的Application
- 自己动手编写web server(二)
- Html之表格在网页中的对齐_实例
- django关于csrf防止跨站的ajax请求403处理
- UI 选择for iphone
- 安装apache_2.2.4时选择only for the Current User, on 8080, when started Manually
- 【Apache Kafka】安装升级指南
- 用ASM实现GetProcAddress()函数
- tomcat配置https访问系统
- Thread safety & Re-entrancy