内容简介: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目录下
结果
其中静态资源存放在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商业环境实战
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C++ Primer Plus
Stephen Prata / Addison Wesley / 2011-10-18 / GBP 39.99
C++ Primer Plus, Sixth Edition New C++11 Coverage C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible an......一起来看看 《C++ Primer Plus》 这本书的介绍吧!