原文链接:http://www.ihuxu.com/p/235.html

 

首先了解下HTTP协议:

wikiPedia的说明很好,在此不重复了。链接:http://zh.wikipedia.org/wiki/Http

源码分析:

概述:此两个代码段,完成服务器监听,线程处理短请求服务和应答(符合伪HTTP协议,“伪”即判断协议格式不严谨)。展示了利用java socket完成http通信的核心原理代码,希望给初次学习socket或者第一次利用java来实现HTTP协议服务器的朋友提供些帮助。

利用 Java Socket 网络编程来绑定服务器某个端口进行监听。

 1 package JHServer;
2
3 import java.io.IOException;
4 import java.net.ServerSocket;
5 import java.net.Socket;
6
7 public class Server {
8
9 private static int PORT = 1720;
10 public static String charset = "utf-8";
11 private ServerSocket ss;
12 private Socket client;
13
14 public static void main(String[] args) {
15 new Server();
16 }
17
18 public Server() {
19 try {
20 this.ss = new ServerSocket(this.PORT);
21 System.out.println("Server Listening Port " + this.PORT + "...");
22 boolean isGo = true;
23 while(isGo){
24 this.client = this.ss.accept();
25 System.out.println("One Client Connected. " + this.client);
26 ClientThread ct = new ClientThread(this.client);
27 Thread t = new Thread(ct);
28 t.start();
29 System.out.println("One Client Thread Already Started...");
30 }
31 } catch (IOException e) {
32 e.printStackTrace();
33 } finally {
34 try{
35 if(this.ss != null){
36 this.ss.close();
37 this.ss = null;
38 }
39 if(this.client != null){
40 this.client.close();
41 this.client = null;
42 }
43 } catch(IOException e) {
44 e.printStackTrace();
45 }
46 }
47 }
48
49 }

说明:上述代码完成了服务端口(1720,你懂么)的监听,并同时利用线程了处理每个客户端(Client )的消息请求,以减少服务器处理”短请求“阻塞问题。

下述代码完成请求是否符合伪HTTP协议,并完成响应消息。

  1 package JHServer;
2
3 import java.io.*;
4 import java.net.Socket;
5 import java.util.Date;
6
7 import action.ManagerEachMatchInfo;
8
9 import view.*;
10
11 public class ClientThread implements Runnable {
12
13 private float requestDelay = (float)0.5;//
14
15 private Socket _s;
16 private BufferedReader i;
17 private PrintStream o;
18
19 public ClientThread(Socket s) {
20 this._s = s;
21 }
22
23 public void run() {
24 try {
25 this.i = new BufferedReader(new InputStreamReader(this._s.getInputStream()));
26 this.o = new PrintStream(this._s.getOutputStream());
27
28 String request = this.getValidRequest();
29
30 if( !request.equals("") ) {
31 System.out.print("当前虚拟机最大可用内存为:");
32 System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");
33 System.out.print("当前,虚拟机已占用内存:");
34 System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");
35 this.o.println("HTTP/1.1 200 OK");
36 Date now = new Date();
37 this.o.println("Data:" + now);
38 this.o.println("Server: JHServer");
39 this.o.println("Access-Control-Allow-Origin:*");
40
41 this.o.println("Content-Type: text/html; charset=UTF-8");
42 this.o.println();
43 String content = null;
44 IndeMatchInfo imi = new IndeMatchInfo(22,22,2,2,22,(double)0.0,"S7-200");
45 content = imi.getHTML();
46
47 imi.clear();
48 imi = null;
49 System.out.print("当前虚拟机最大可用内存为:");
50 System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");
51 System.out.print("当前,虚拟机已占用内存:");
52 System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");
53
54 this.o.println(content);
55 content = "";
56 this.o.flush();
57
58 }
59
60 } catch (IOException e) {
61 e.printStackTrace();
62 } finally {
63 this.close();
64 }
65
66 }
67
68 private String getValidRequest() {
69
70 float second = (float) 0.0;
71 boolean isGo = true;
72 String request = null;
73 try {
74 while (!this.i.ready()) {
75 second += 0.01;
76 if (second > this.requestDelay) {
77 System.out.println("One Client Delayed " + this._s);
78 isGo = false;
79 break;
80 }
81 Thread.sleep(10);
82 }
83
84 if (isGo == true) {
85 request = this.i.readLine();
86 if( request.contains("GET /") && request.contains(" HTTP/") ) {
87 request = request.substring(request.indexOf("/"),request.indexOf(" HTTP/"));
88 System.out.println("Client Request Info: " + request);
89 } else {
90 isGo = false;
91 }
92 }
93 } catch (InterruptedException e) {
94 e.printStackTrace();
95 } catch (IOException e) {
96 e.printStackTrace();
97 } finally {
98 if(isGo == true) {
99 return request;
100 } else {
101 return "null";
102 }
103 }
104 }
105
106 private void close() {
107 try {
108 if (this.i != null) {
109 this.i.close();
110 this.i = null;
111 }
112 if (this.o != null) {
113 this.o.close();
114 this.o = null;
115 }
116 if (this._s != null) {
117 this._s.close();
118 this._s = null;
119 }
120 System.out.println("One Client Disconnected...");
121 } catch (IOException e) {
122 e.printStackTrace();
123 }
124 }
125
126 }

说明:

1、getValidRequest() 验证请求消息是否满足伪HTTP协议。比如:GET /images/logo.gif HTTP/1.1,则会返回"/images/logo.gif"。若不符合伪HTTP协议或者请求时不发送任何消息头(比如通过telnet访问,此情况最大延迟0.5秒),则会返回空串。

2、close(),释放内存,同时线程结束。

3、run(),短请求的线程主体,在此处可以进行数据逻辑处理,并返回特定消息内容。

Java Socket 实现HTTP服务器核心的更多相关文章

  1. 实现服务器和客户端数据交互,Java Socket有妙招

    摘要:在Java SDK中,对于Socket原生提供了支持,它分为ServerSocket和Socket. 本文分享自华为云社区<Java Socket 如何实现服务器和客户端数据交互>, ...

  2. JAVA基础知识之网络编程——-TCP/IP协议,socket通信,服务器客户端通信demo

    OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七 ...

  3. java 网络编程 TCP协议 java 服务器和客户端 java socket编程

    一个 HelloWord 级别的 Java Socket 通信的例子.通讯过程:        先启动 Server 端,进入一个死循环以便一直监听某端口是否有连接请求.然后运行 Client 端,客 ...

  4. 使用Java Socket手撸一个http服务器

    原文连接:使用Java Socket手撸一个http服务器 作为一个java后端,提供http服务可以说是基本技能之一了,但是你真的了解http协议么?你知道知道如何手撸一个http服务器么?tomc ...

  5. 移动开发首页业界资讯移动应用平台技术专题 输入您要搜索的内容 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)

    在阅读本文前需要对socket以及自定义协议有一个基本的了解,可以先查看上一篇文章<基于Java Socket的自定义协议,实现Android与服务器的长连接(一)>学习相关的基础知识点. ...

  6. JAVA Socket连接服务器时可能抛出的异常

    1.UnknownHostException:host(非ip)无法识,就会报该异常,www.google.com.hk这个虽然也ping不通,但是不会报该错,因为他是一个确实存在的域名.他会报Con ...

  7. java socket 服务器多线程 数据转发的研究实践

    项目中借鉴了以下资料: https://www.cnblogs.com/whenever/p/5526420.html https://www.cnblogs.com/jpwz/p/5715852.h ...

  8. Java Socket编程如何建立两者关系

    转自:http://developer.51cto.com/art/201003/190582.htm Java Socket编程需要大家详细的学习,有关的技术一直在不断的更新.那么要如何才能掌握好有 ...

  9. JAVA通信系列一:Java Socket技术总结

    本文是学习java Socket整理的资料,供参考. 1       Socket通信原理 1.1     ISO七层模型 1.2     TCP/IP五层模型 应用层相当于OSI中的会话层,表示层, ...

随机推荐

  1. AlexNet网络结构特点总结

    参考论文:ImageNet Classification with Deep Convolutional Neural Networks 1.特点 1.1 ReLU Nonlinearity的提出 Re ...

  2. 数组类型的退化Decay

    Decay即数组在某些情况下将退化为指针. 测试代码: #include <iostream> #include <typeinfo> template <typenam ...

  3. Linux-Ubuntu14.04下mongodb安装部署

    mongo 下载:https://www.mongodb.com/download-center/community?jmp=nav 创建目录,将下载的文件放在如下位置 xxx@ubuntu:/usr ...

  4. Oracle数据库常见版本

    Oracle数据库常见版本 在Oracle数据库的发展中,数据库一直处于不断升级状态,有以下几个版本: Oracle 8,Oracle 8i:Oracle 8i表示Oracle正式向Internet上 ...

  5. django 动态生成CSV文件

    CSV (Comma Separated Values),以纯文本形式存储数字和文本数据的存储方式.纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样的数据.CSV文件由任意数目的记录组成,记 ...

  6. MKAnnotationView和MKPinAnnotationView的区别

    如果想创建以静态图片作为大头针图片的话,可以通过创建MKAnnotationView是实例.如果想使用apple自带的大头针则创建MKPinAnnotationView

  7. Codeforces 798A - Mike and palindrome

    A. Mike and palindrome time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  8. Unity另外一套简单日志控制系统

    using UnityEngine; public class LogPrintf { static LogLevel logLevel = LogLevel.LOG_LEVEL_ERROR; pub ...

  9. mysql 随机获取数据并插入到数据库中

    insert into result (user_id, activity_id, number) select user_id, activity_id from `activity_record` ...

  10. 『Scipy』常用方法记录

    优化器使用教程 J = lambda wb: self.get_cost_grad(wb, X, Y_one_hot) theta = self.wb_init(X,Y_one_hot) result ...