package exec2;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
/**
*
* @author wjl
*/
public class HttpHandler implements Runnable { // 负责与单个客户通信的线程
private Socket socket;
private final String getPath = "C:\\Users\\14551\\Desktop\\internet\\gets\\";//服务器端GET内容存放路径
private final String putPath = "C:\\Users\\14551\\Desktop\\internet\\puts\\";//服务器端PUT内容存放路径
private String response;
BufferedOutputStream ostream = null;
BufferedInputStream istream = null;
private static int buffer_size = 8192;
private byte[] buffer;
static private String CRLF = "\r\n";
public HttpHandler(Socket socket) {
this.socket = socket;
this.buffer = new byte[buffer_size];
this.response = "";
}
public void initstream() throws IOException {
ostream = new BufferedOutputStream(socket.getOutputStream());
istream = new BufferedInputStream(socket.getInputStream());
}
public void run() { // 执行的内容
try {
System.out.println("新连接,连接地址:" + socket.getInetAddress() + ":" + socket.getPort()); // 客户端信息
initstream();
istream.read(buffer);
String request = new String(buffer, "iso-8859-1");
System.out.println("request from "+ socket.getInetAddress() + ":" + socket.getPort()+":\n"+request);
//分类处理
if (request.startsWith("GET")) {
responseForGet(request);
} else if (request.startsWith("PUT")) {
responseForPut(request);
} else {
responseForBadRequest();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != socket) {
try {
ostream.close();
istream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public String getGmtTime() {//获取当前GMT时间
Date d = new Date();
DateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
return format.format(d);
}
/**
* 对于非PUT或GET请求的响应以及错误请求
*/
public void responseForBadRequest() throws IOException {
response = "HTTP/1.1 400 Bad Request";
ostream.write(response.getBytes(),0,response.length());
ostream.flush();
}
/**
* 对于PUT请求的响应
*/
public void responseForPut(String request) throws FileNotFoundException, Exception {
String str[] = request.split(" ");//预处理请求
response = "";
if (str.length != 3) {//非法请求
responseForBadRequest();
return;
}
if (!str[2].startsWith("HTTP/1.0")) {//非HTTP1.0版本的请求
responseForBadRequest();
return;
}
if(str[1].startsWith("/"));
str[1]=str[1].substring(1);
String filename = putPath + str[1];
FileOutputStream outfile = new FileOutputStream(filename);
String strr[] =str[2].split(CRLF);
long filelength = 0;//得到PUT文件的大小
for(int i=0;i<strr[2].length();i++) {
if(strr[2].charAt(i)>='0'&& strr[2].charAt(i)<='9')
filelength=filelength*10+strr[2].charAt(i)-'0';
else break;
}
long pos=0;
buffer = new byte[buffer_size];
StringBuffer sb= new StringBuffer();
//接收客户端PUT的文件
while (pos < filelength) {
if (pos + buffer_size < filelength) {
istream.read(buffer);
pos += buffer_size;
} else {
buffer = new byte[(int) (filelength - pos)];
istream.read(buffer);
pos = filelength;
}
sb.append(new String(buffer, "iso-8859-1"));
}
//写入文件
outfile.write(sb.toString().getBytes("iso-8859-1"));
outfile.flush();
outfile.close();
response += "HTTP/1.0 201 Created" + CRLF + "Server: MyHttpServer/1.0" + CRLF+"Date: " + getGmtTime() + CRLF;
response += "Content-length: " + 141 + CRLF;
response += "Content-Type: " + "text/html" + "; charset=iso-8859-1" + CRLF;// 获取文件类型
response += "Connection: close" + CRLF;
//header结束
response += CRLF;
//返回报文内容
response += "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">" + CRLF + "<html><head>" + CRLF
+ "<title>201 Created</title>" + CRLF + "</head><body>" + CRLF + "<h1>Created</h1>" + CRLF
+ "</body></html>";
ostream.write(response.getBytes(),0,response.length());
ostream.flush();
}
/**
* 对于GET请求的响应
*/
public void responseForGet(String request) throws FileNotFoundException, IOException {
String str[] = request.split(" ");//处理请求
response = "";
if (str.length != 3) {// 不是合法要求的请求
responseForBadRequest();
return;
}
if (!str[2].startsWith("HTTP/1.0")) {// 不处理HTTP/1.0以外版本的请求
responseForBadRequest();
return;
}
String filename = getPath + str[1];
File file = new File(filename);
if (file.exists() && !file.isDirectory()) {//文件存在且非目录文件 返回200报文
FileInputStream infile = new FileInputStream(filename);
byte[] buf = new byte[infile.available()];
//获取当前GMT时间
response += "HTTP/1.0 200 OK" + CRLF + "Server: MyHttpServer/1.0" + CRLF +"Date: "+ getGmtTime() + CRLF;
//获取文件长度
response += "Content-length: " + infile.available() + CRLF;
// 获取文件类型
response += "Content-Type: " + Files.probeContentType(Paths.get(filename)) + "; charset=iso-8859-1" + CRLF;
//HTTP/1.0 连接关闭
response += "Connection: close" + CRLF;
// header 结束
response += CRLF;
// 先将头部信息发送过去
ostream.write(response.getBytes(),0,response.length());
while (infile.read(buf) != -1) {// 与接收端相对应的发送
ostream.write(buf);
}
ostream.flush();
infile.close();
} else {// 文件找不到或者是目录文件返回404报文
response = "HTTP/1.1 404 Not Found" + CRLF + "Date:" + getGmtTime() + CRLF + "Content-Length: 0" + CRLF
+ "Connection: close" + CRLF;
ostream.write(response.getBytes(),0,response.length());
ostream.flush();
}
}
}