import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.cert.TrustAnchor;
import java.util.Date;
import java.util.Scanner;
import java.util.Vector;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static java.lang.Thread.sleep;
// 通信线程
class ClientThread implements Runnable {
private Socket client; // 客户端套接字
// private DataInputStream in; // 输入流
private int type; // 请求类型: 1 - html, 2 - txt, 3 - img
private String postfix; // 请求图片时使用
public ClientThread(Socket s) throws IOException, InterruptedException {
// System.out.println("port: " + s.getPort() +" " + (new Date()).toString());
this.client = s;
}
// 获取请求资源路径(除前缀)
public String getResourcePath(String s)
{
//获取资源的位置
int begin = s.indexOf(' ')+1;
int end = s.indexOf(' ', begin);
String name = s.substring(begin, end);
if (name.equals("/html/dopost"))
{
name = "/dopost";
return name;
}
// 区分请求类型
String r_type = s.substring(0, begin-1);
System.out.print(r_type + ": ");
//默认请求(转到test.html)
if (name.equals("/")) {
name = "/html/test.html";
System.out.println("index.html");
} else {
System.out.println(name);
}
// 区分资源类型
postfix = name.substring(name.indexOf('.')+1);
// System.out.println("postfix:" + postfix);
if (postfix.equals("html") || postfix.equals("htm"))
type = 1;
else if(postfix.equals("txt"))
type = 2;
else if(postfix.equals("jpg") || postfix.equals("jpeg"))
type = 3;
else
type = 0;
return name;
}
// 返回404
public void NotFound() throws IOException
{
StringBuffer err = new StringBuffer();
DataOutputStream out = new DataOutputStream(client.getOutputStream());
err.append("HTTP/1.1 404 file not found\r\n" + "Content-Type:text/html\r\n" + "Content-Length:22\r\n" + "\r\n" + "
404 Not Found
");
try
{
out.write(err.toString().getBytes());
out.flush();
out.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
// 响应处理
public void response(File file)
{
try {
DataOutputStream out = new DataOutputStream(client.getOutputStream());
//根据响应报文格式设置
out.write("HTTP/1.0 200 OK\r\n".getBytes());
out.write("Server: MyWebServer\r\n".getBytes());
out.write(("Date: " + (new Date()).toString() + "\r\n").getBytes());
switch(type)
{
case 1: // html
out.write("Content-Type:text/html\r\n".getBytes());
break;
case 2: // txt
out.write("Content-Type:text/plain\r\n".getBytes());
break;
case 3: // jpg
out.write("Content-Type:image/jpeg\r\n".getBytes());
break;
default:
out.write("Content-Type:text/plain\r\n".getBytes());
break;
}
int len = (int) file.length();
out.write(("Content-Length:" + len + "\r\n").getBytes());
out.write("\r\n".getBytes());//报文头和信息之间要空一行
// 读取文件
DataInputStream in = new DataInputStream(new FileInputStream(file));
byte buf[] = new byte[len];
in.readFully(buf);
// 发送文件
out.write(buf, 0, len);
out.flush();
in.close();
out.close();
}
catch (Exception e)
{
System.out.println(e.getMessage());
System.exit(1);
}
}
public void check() throws IOException
{
boolean flag = false;
int len = 0;
DataInputStream in = new DataInputStream(client.getInputStream());
// 获取文本长度
while(true)
{
String line = in.readLine();
if(line.length() == 0) break;
int pos = line.indexOf(':');
String key = line.substring(0, pos);
if(key.equals("Content-Length")) {
len = Integer.parseInt(line.substring(pos+2));
}
}
// 校验信息
char[] txt = "login=3200104392&pass=4392".toCharArray();
if(len == 26)
{
int i;
for(i = 0 ; i < 26; i++)
{
char c = (char)in.read();
if(c != txt[i]) break;
}
// 检验通过
if(i == 26)
flag = true;
}
DataOutputStream out = new DataOutputStream(client.getOutputStream());
// 返回验证结果
out.write("HTTP/1.0 200 OK".getBytes());
out.write("Content-Type:text/html".getBytes());
if (flag)
{
out.write("Content-Length:22\r\n".getBytes());
out.write("\r\n".getBytes());
out.write("Login Success!".getBytes());
}
else
{
out.write("Content_Length:21\r\n".getBytes());
out.write("\r\n".getBytes());
out.write("Login Failed!".getBytes());
}
out.flush();
out.close();
}
@Override
public void run()
{
try
{
// 读取浏览器提交的请求
DataInputStream in = new DataInputStream(client.getInputStream());
String msg = in.readLine();
String method = msg.substring(0, msg.indexOf(' '));
if(method.equals("GET"))
{
// 获取文件路径
String fileName = getResourcePath(msg);
String prefix = "D:\\wwwroot"; // 此处默认读取D盘wwwroot目录下的文件,可以对字符串进行更改
File file = new File(prefix + fileName);
if (file.exists())
{
System.out.println("开始发送:" + fileName);
response(file);
}
else
{ // 错误处理
System.out.println("错误:未找到文件");
NotFound();
}
}
else if (method.equals("POST"))
{
System.out.println("hanle post");
if(!getResourcePath(msg).equals("/dopost"))
{
System.out.println("错误:路径不是dopost");
NotFound();
}
else
check();
}
client.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class Handle implements Runnable { // 监听客户端请求
private ExecutorService threadPool = Executors.newFixedThreadPool(20);
private ServerSocket server;
public Handle(int Port) throws IOException {
ServerSocket server = new ServerSocket(Port);
System.out.println("初始化完毕,正在监听端口:" + server.getLocalPort());
this.server = server;
}
@Override
public void run()
{
while(true)
{
Socket clientSocket = null;
try
{
clientSocket = server.accept();
}
catch (IOException e)
{
break;
}
if (clientSocket != null && !clientSocket.isClosed())
{
try
{
threadPool.execute(new ClientThread(clientSocket)); // 通过线程池中分配一个线程
}
catch (IOException | InterruptedException e)
{
throw new RuntimeException(e);
}
}
}
}
public void stop() throws IOException {
threadPool.shutdownNow();
server.close();
System.out.println("服务器已停止运行!");
}
}
// 服务器线程
public class WebServer {
private static int Port = 4392; // http://dns-name:port/file.监听端口号
public static void main(String[] args)
{
// ExecutorService threadPool = Executors.newFixedThreadPool(20);
try {
// 创建服务器,监听客户端请求的线程
Handle h = new Handle(Port);
new Thread(h).start();
System.out.println("您可以输入'exit'以结束运行");
while(true)
{
Scanner in = new Scanner(System.in);
String input = in.nextLine();
if(input.equals("exit"))
{
h.stop();
break;
}
}
}
catch
(Exception e)
{
e.printStackTrace();
}
}
}