From 260d6e57fd524a31c4397e5aff48d56bd856ff77 Mon Sep 17 00:00:00 2001 From: j502647092 Date: Tue, 28 Jul 2015 21:02:56 +0800 Subject: [PATCH] add HTTP Handle Class and Complete AuthMe Hook... --- .../Socket/CTZLoginServerSocket.java | 140 ++++++++++++++---- .../CTZLoginServer/Socket/Request.java | 106 +++++++++++++ .../CTZLoginServer/Socket/Response.java | 79 ++++++++++ 3 files changed, 298 insertions(+), 27 deletions(-) create mode 100644 src/cn/citycraft/CTZLoginServer/Socket/Request.java create mode 100644 src/cn/citycraft/CTZLoginServer/Socket/Response.java diff --git a/src/cn/citycraft/CTZLoginServer/Socket/CTZLoginServerSocket.java b/src/cn/citycraft/CTZLoginServer/Socket/CTZLoginServerSocket.java index 507aadb..be38df5 100644 --- a/src/cn/citycraft/CTZLoginServer/Socket/CTZLoginServerSocket.java +++ b/src/cn/citycraft/CTZLoginServer/Socket/CTZLoginServerSocket.java @@ -8,7 +8,10 @@ import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; +import org.bukkit.Bukkit; + import cn.citycraft.CTZLoginServer.CTZLoginServer; +import cn.citycraft.CTZLoginServer.Socket.Response.HttpStates; import fr.xephi.authme.api.API; public class CTZLoginServerSocket implements Runnable { @@ -28,48 +31,131 @@ public class CTZLoginServerSocket implements Runnable { public void run() { ServerSocket s = null; Socket socket = null; - BufferedReader br = null; - PrintWriter pw = null; + try { // 设定服务端的端口号 - s = new ServerSocket(PORT); - System.out.println("CTZL服务器开始监听:" + s); + s = new ServerSocket(2000); + System.out.println("CTZL服务器开始监听 端口:" + s.getLocalPort()); // 等待请求,此方法会一直阻塞,直到获得请求才往下走 while (true) { socket = s.accept(); - // 用于接收客户端发来的请求 - br = new BufferedReader(new InputStreamReader(socket.getInputStream())); - // 用于发送返回信息,可以不需要装饰这么多io流使用缓冲流时发送数据要注意调用.flush()方法 - pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter( - socket.getOutputStream())), true); - while (true) { - if (socket.isClosed()) { - break; - } - String str = br.readLine(); - if (str.equals("END")) { - break; - } - Thread.sleep(1000); - API.isRegistered(str); - pw.println("Message Received"); - pw.flush(); - } + System.out.println("CTZL服务器收到请求 客户端IP: " + socket.getRemoteSocketAddress() + " 端口:" + + socket.getPort()); + new ClientThread(socket).start(); } - } catch (Exception e) { System.out.println("CTZL服务器崩溃..."); } finally { System.out.println("关闭连接"); try { - br.close(); - pw.close(); socket.close(); s.close(); } catch (Exception e2) { - } } } -} + class ClientThread extends Thread { + Socket client = null; + BufferedReader br = null; + PrintWriter pw = null; + + public ClientThread(Socket client) { + this.client = client; + } + + @Override + public void run() { + try { + // 用于接收客户端发来的请求 + br = new BufferedReader(new InputStreamReader(client.getInputStream())); + // 用于发送返回信息,可以不需要装饰这么多io流使用缓冲流时发送数据要注意调用.flush()方法 + pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter( + client.getOutputStream())), true); + while (true) { + String str = br.readLine(); + if (str != null) { + Request req = new Request(str); + Response res = new Response(); + String username = ""; + String password = ""; + if (req.isSuccess) { + switch (req.getPrefix().substring(1)) { + case "isregister": + username = req.getQuerystring("username"); + if (username == null) { + res.setState(HttpStates.Bad_Request); + break; + } + if (API.isRegistered(username)) + res.setHtml("true"); + else + res.setHtml("false"); + break; + case "register": + username = req.getQuerystring("username"); + password = req.getQuerystring("password"); + if (username == null || password == null) { + res.setState(HttpStates.Bad_Request); + break; + } + if (API.registerPlayer(username, password)) + res.setHtml("true"); + else + res.setHtml("false"); + break; + case "login": + username = req.getQuerystring("username"); + password = req.getQuerystring("password"); + if (username == null || password == null) { + res.setState(HttpStates.Bad_Request); + break; + } + if (API.checkPassword(username, password)) + res.setHtml("true"); + // TODO 处理玩家后续登录事件 + else + res.setHtml("false"); + break; + case "islogin": + username = req.getQuerystring("username"); + if (username == null) { + res.setState(HttpStates.Bad_Request); + break; + } + if (Bukkit.getPlayer(username) != null) + res.setHtml("true"); + else + res.setHtml("false"); + break; + case "changepassword": + username = req.getQuerystring("username"); + password = req.getQuerystring("password"); + if (username == null) { + res.setState(HttpStates.Bad_Request); + break; + } + if (API.checkPassword(username, password)) + res.setHtml("true"); + // TODO 处理玩家密码修改事件 + else + res.setHtml("false"); + break; + default: + res.setState(HttpStates.Bad_Request); + } + System.out.println(res.toString()); + pw.write(res.toString()); + pw.flush(); + } + break; + } + } + br.close(); + pw.close(); + client.close(); + } catch (Exception e) { + } + } + } +} \ No newline at end of file diff --git a/src/cn/citycraft/CTZLoginServer/Socket/Request.java b/src/cn/citycraft/CTZLoginServer/Socket/Request.java new file mode 100644 index 0000000..2eb6ede --- /dev/null +++ b/src/cn/citycraft/CTZLoginServer/Socket/Request.java @@ -0,0 +1,106 @@ +/** + * + */ +package cn.citycraft.CTZLoginServer.Socket; + +import java.util.HashMap; + +/** + * @author 蒋天蓓 + * 2015年7月28日下午4:58:26 + * HTTP 头文件解析类 + * 目前只能解析GET + */ +public class Request { + protected boolean isSuccess = false; + protected String prefix; + protected Method method; + protected String version; + protected HashMap querystring = new HashMap(); + + enum Method { + GET, POST + } + + /** + * 解析字符串为Response + * + * @param response + */ + public Request(String response) { + try { + String[] args = response.split(" "); + // 解析协议 + if (args[0].equalsIgnoreCase(Method.GET.toString())) + method = Method.GET; + else + method = Method.POST; + // 判断是否有查询字符串 + if (args[1].contains("?")) { + // 获得分割符?的位置 + int lastc = args[1].indexOf("?"); + // 解析URL + prefix = args[1].substring(0, lastc); + // 解析查询字符串 + String[] params = args[1].substring(lastc).split("&"); + for (String param : params) { + if (param.contains("=")) { + String[] paraminfo = param.split("="); + querystring.put(paraminfo[0], paraminfo[1]); + } + } + } else { + // 直接配置为区域 + prefix = args[1]; + } + // 解析HTTP版本 + version = args[2]; + isSuccess = true; + } catch (Exception e) { + } + } + + /** + * @return 获得前缀区域 + */ + public String getPrefix() { + return prefix; + } + + /** + * @return 获得查询字符集 + */ + public HashMap getQuerystring() { + if (querystring.isEmpty()) + return null; + return querystring; + } + + /** + * @return 查询数据 + */ + public String getQuerystring(String key) { + return querystring.get(key); + } + + /** + * @return 获得请求方式 + */ + public Method getMethod() { + return method; + } + + /** + * @return 获得HTTP版本 + */ + public String getVersion() { + return version; + } + + /** + * @return 是否转换成功 + */ + public boolean isSuccess() { + return isSuccess; + } +} diff --git a/src/cn/citycraft/CTZLoginServer/Socket/Response.java b/src/cn/citycraft/CTZLoginServer/Socket/Response.java new file mode 100644 index 0000000..10cbc98 --- /dev/null +++ b/src/cn/citycraft/CTZLoginServer/Socket/Response.java @@ -0,0 +1,79 @@ +/** + * + */ +package cn.citycraft.CTZLoginServer.Socket; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map.Entry; + +/** + * @author 蒋天蓓 + * 2015年7月28日下午7:19:28 + * HTTP客户端响应类 + */ +public class Response { + protected HttpStates state = HttpStates.OK; + protected String version = "HTTP/1.1"; + protected HashMap header = new HashMap(); + protected String html = ""; + + public enum HttpStates { + + OK(200), // 客户端请求成功 + Bad_Request(400), // 客户端请求有语法错误,不能被服务器所理解 + Unauthorized(401), // 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 + Forbidden(403), // 服务器收到请求,但是拒绝提供服务 + Not_Found(404), // 请求资源不存在,eg:输入了错误的URL + Internal_Server_Error(500), // 服务器发生不可预期的错误 + Server_Unavailable(503); // 服务器当前不能处理客户端的请求,一段时间后可能恢复正常 + + private int num = 0; + + /** + * @return 返回状态所表示的代码 + */ + public int getNum() { + return num; + } + + HttpStates(int num) { + this.num = num; + } + + @Override + public String toString() { + return super.toString().replace("_", " "); + } + } + + public Response() { + header.put("Date", new Date().toString() + " GMT"); + header.put("Server", "Minecraft-CTZLoginServer"); + header.put("Content-Type", "text/html; charset=UTF-8"); + } + + public void setHtml(String html) { + this.html = html; + } + + public void setState(HttpStates state) { + this.state = state; + } + + public void setHeader(String key, String value) { + header.put(key, value); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(version + " " + state.getNum() + " " + state.toString() + "\r\n"); + for (Entry entry : header.entrySet()) { + sb.append(entry.getKey() + ": " + entry.getValue() + "\r\n"); + } + sb.append("\r\n"); + sb.append(this.html); + return sb.toString(); + } +}