内容简介:Java实现简单的站点请求模式
Java实现简单的站点请求模式
概述
本次实现的是浏览器(客户端)访问特定站点ip和端口,自定义socket来监听该请求,解析请求内容以及做出响应。
以下是在com.yzz.tomcat下的三个类
- HttpServer:socket监听ip,接收客户端请求。
- HttpRequest:解析客户端HTTP请求。
- HttpResponse:对客户端请求做出响应。
HttpServer
await()方法这里面包括了socket的创建,连接的监听,对HTTP请求的解析以及对请求做出响应。
package com.yzz.tomcat.server; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import com.yzz.tomcat.request.HttpRequest; import com.yzz.tomcat.response.HttpResponse; public class HttpServer { //获取项目中的文件 public static final String WEEB_ROOT = System.getProperty("user.dir")+File.separator+"webroot"; //关闭监听字符 public static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; //是否监听关闭 private boolean shutdown = false; /** * 这里是对特定ip端口进行监听 * 监听8080端口 * ip是本地ip */ public void await(){ ServerSocket serverSocket = null; int port = 8080; try{ serverSocket = new ServerSocket(port,100,InetAddress.getByName("127.0.0.1")); }catch (Exception e) { e.printStackTrace(); System.out.println("serverSocket获取失败"); } while(!shutdown){ Socket socket = null; InputStream input = null; OutputStream output = null; try { //The method blocks until a connection is made. socket = serverSocket.accept(); //设置读取超时时间 socket.setSoTimeout(3000); //获取出入输出流 input = socket.getInputStream(); output = socket.getOutputStream(); //创建HttpRequest对象,调用parse()方法来解析HTTP请求 HttpRequest request = new HttpRequest(input); request.parse(); //新建HttpResponse对象,对请求进行对应的处理 HttpResponse response = new HttpResponse(output); response.setHttpRequest(request); //向客户端发送静态的资源 response.sendStaticResource(); //在做出响应后,关闭socket连接 socket.close(); //判断是否是客户端发来的关闭监听指令 shutdown = request.getUri().equals(SHUTDOWN_COMMAND); } catch (Exception e) { e.printStackTrace(); continue; } } } }
HttpRequest
这里需要特别注意的是,在读取HTTP请求内容的时候与普通的文件流有所区别,详情见注释
package com.yzz.tomcat.request; import java.io.InputStream; public class HttpRequest { //socket连接的输入流 private InputStream inputStream; //统一字段标识符 private String uri; //HTTP请求内容 private StringBuffer request; public HttpRequest(InputStream inputStream) { this.inputStream = inputStream; } /** * 解析HTTP请求 * 这里只是对HTTP协议的第一行的URI做了解析,其他内容这里并没有做关注 * 注意:socket的输入流的文件流有区别,文件流可以循环读取,直到出现某一个标志位,结束 * 但是socket的输入流不满足这种情况,当读取完成之后,流会处于等待状态,并没有结束,因为是端对端的传输,不知道 * 客户端时候是传输完毕了,所以会处于无限期的等待状态中。 * 解决:目前的解决办法是一次性读完所有的HTTP请求资源,这里是2048byte */ public void parse() { request = new StringBuffer(); try { if (null == inputStream) return; byte buf[] = new byte[2048]; int len = 0; len = inputStream.read(buf); if(len != -1) request.append(new String(buf,0,len)); System.out.println(request.toString()); parseUri(); } catch (Exception e) { e.printStackTrace(); } } /** * 解析URI */ private void parseUri() { int index1; int index2; index1 = request.indexOf(" "); index2 = request.indexOf(" ", index1 + 1); if (index2 > index1) uri = request.substring(index1 + 1, index2); System.out.println("uri:"+uri); } public String getUri() { return uri; } }
HttpResponse
响应做的比较简单,请求的资源存在就将资源通过输出流返回给客户端,否则返回404页面
package com.yzz.tomcat.response; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import com.yzz.tomcat.request.HttpRequest; import com.yzz.tomcat.server.HttpServer; public class HttpResponse { //socket连接输出流 private OutputStream out; //HTTP请求对象 private HttpRequest httpRequest; //缓冲byte数组长度 public static final int BUFFER_SIZE = 1024; //404 URI public static final String PAGE_404 = "/404.html"; public HttpResponse(OutputStream out) { this.out = out; } public void setHttpRequest(HttpRequest httpRequest) { this.httpRequest = httpRequest; } /** * 向客户端响应静态资源 */ public void sendStaticResource() { File file = new File(HttpServer.WEEB_ROOT, httpRequest.getUri()); FileInputStream fis = null; if(!file.exists()){ file = new File(HttpServer.WEEB_ROOT+PAGE_404); } try { fis = new FileInputStream(file); byte[] buf = new byte[BUFFER_SIZE]; int len = 0; while ((len = fis.read(buf)) != -1) { out.write(buf, 0, len); } } catch (Exception e) { e.printStackTrace(); }finally { if(null != fis){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
演示
工程结构
其中静态资源存放在tomcat的webroot目录下
结果
1. 正常请求
2. 错误请求
3. 结束监听
总结
本次只是简单的对socket进行了利用,对于响应还没有加上HTTP规范,下片我们继续来优化。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 如何使用策略模式处理多种类型请求
- 常用设计模式/容器/依赖注入/静态代理/请求对象
- 论RAC+MVVM 模式下的网络请求
- Reactor-Guice 0.0.8 发布 ,支持 API 网关模式、跨域请求
- Reactor-Guice 0.0.8 发布 ,支持 API 网关模式、跨域请求
- kafka集群Broker端基于Reactor模式请求处理流程深入剖析-kafka商业环境实战
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ACM国际大学生程序设计竞赛亚洲区预选赛真题题解
郭炜 / 电子工业 / 2011-7 / 49.00元
ACM国际大学生程序设计竞赛(ACM International Collegiate Programming Contest,简称ACM/ICPC)是世界上历史最悠久,规模最大、最具声望的程序设计竞赛,一直受到众多国际知名大学的重视,全球著名IT公司更是争相招募竞赛的优胜者。 该项赛事分为各大洲预选赛和全球总决赛两个阶段。北京大学多次在亚洲区预选赛中负责命题工作,是中国在ACM/ICPC命......一起来看看 《ACM国际大学生程序设计竞赛亚洲区预选赛真题题解》 这本书的介绍吧!