http协议

若是两个人能正常的说话交流,那么他们间必然有一套统一的语言规则<在网络上server与client能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertext transfer protocol)。

http分两部分,一个是请求(client发给server),一个是回复(server发给client)。

先看http请求

以下就是一个http请求的样例,当中的各项參数,请查阅相关文档。(http://www.cnblogs.com/yin-jingyu/archive/2011/08/01/2123548.html)

http回复

以下就是http回复的样例,除了这个图之外,后面的部分就是大家看到的页面的源码

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGxmMTIzMzIx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

socket

我们一般说的socket,广义上包括java.net包下的Socket类与ServerSocekt类。

还有一方面有基于tcp的网络编程也有基于udp的网络编程,当中区别大家百度,这里仅仅谈tcp。

定义性的东西大家能够查看各种资料(个人推荐尚学堂 马士兵老师解说的socket部分视频,但在看socket之前建议大家先看io部分),带大家看一段代码,大家应该就会知道socket编程的大致原理了。(代码来自马士兵老师的讲义)

import java.net.*;
import java.io.*; public class TCPServer {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(6666); //在本机的TCP6666号端口上监听
while(true) {
Socket s = ss.accept(); //ServerSocket的accept为堵塞式方法,仅仅有当它监听到一个请求时
//它才会运行
System.out.println("a client connect!");
DataInputStream dis = new DataInputStream(s.getInputStream());//获得客户端向自己说的"话"
//InputStream 从外部指向内存
System.out.println(dis.readUTF()); //依照uft-8的格式读取内容
dis.close();
s.close();
} }
} import java.net.*;
import java.io.*; public class TCPClient {
public static void main(String[] args) throws Exception {
Socket s = new Socket("127.0.0.1", 6666); //连接127.0.0.1(本机)的tcp端口6666
OutputStream os = s.getOutputStream(); //获得一条线路,来给服务器"说话"
DataOutputStream dos = new DataOutputStream(os);//对这个线路进行包装
Thread.sleep(3000); //"暂停"3秒
dos.writeUTF("hello server!"); //对服务器说 hello server!
dos.flush();
dos.close();
s.close();
}
}

先执行server端,再执行client端。当执行client端后,控制台首先会打印a client connect!三秒之后会打印hello server!

模拟一个最最最基础的tomcat

import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.File; public class HttpServer { /** WEB_ROOT is the directory where our HTML and other files reside.
* For this package, WEB_ROOT is the "webroot" directory under the working
* directory.
* The working directory is the location in the file system
* from where the java command was invoked.
*/
public static final String WEB_ROOT =
System.getProperty("user.dir") + File.separator + "webroot"; // shutdown command
private static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; // the shutdown command received
private boolean shutdown = false; public static void main(String[] args) {
HttpServer server = new HttpServer();
server.await();
} public void await() {
ServerSocket serverSocket = null;
int port = 8080;
try {
serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
//这个1是什么功能 參加 http://www.51cto.com/art/200702/40196_1.htm
}
catch (IOException e) {
e.printStackTrace();
System.exit(1);
} // Loop waiting for a request
while (!shutdown) { //最開始的时候 shutdown为false 这段话会执行
Socket socket = null;
InputStream input = null;
OutputStream output = null;
try {
socket = serverSocket.accept(); //仅仅有当有client请求时 它才会执行 堵塞式方法!
System.out.println(new Date()+"AAAAAAAAAAAA");
 input = socket.getInputStream(); //里面放的是client对server说的话
output = socket.getOutputStream();//这里面将要放的是server要对client说的话 // create Request object and parse
Request request = new Request(input);
request.parse(); //參见request // create Response object
Response response = new Response(output);
response.setRequest(request);
response.sendStaticResource(); // Close the socket
socket.close(); //check if the previous URI is a shutdown command
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
}
catch (Exception e) {
e.printStackTrace();
continue;
}
}
}
}
import java.io.InputStream;
import java.io.IOException; public class Request { private InputStream input;
private String uri; public Request(InputStream input) {
this.input = input;
} public void parse() {
// Read a set of characters from the socket
StringBuffer request = new StringBuffer(2048);
int i;
byte[] buffer = new byte[2048];
try {
i = input.read(buffer);
}
catch (IOException e) {
e.printStackTrace();
i = -1;
}
for (int j=0; j<i; j++) {
request.append((char) buffer[j]); //将client的请求加到request(StringBuffer)中
}
    System.out.println("request 例如以下");
    System.out.print(request.toString());
    uri = parseUri(request.toString());
    System.out.println("uri 例如以下  "+uri);
} /**
*看看System.out.println("uri 例如以下  "+uri); 就不用解释这种方法了
*
**/
private String parseUri(String requestString) {
int index1, index2;
index1 = requestString.indexOf(' ');
if (index1 != -1) {
index2 = requestString.indexOf(' ', index1 + 1);
if (index2 。 index1)
return requestString.substring(index1 + 1, index2);
}
return null;
} public String getUri() {
return uri;
} }
import java.io.OutputStream;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.File; /*
HTTP Response = Status-Line
*(( general-header | response-header | entity-header ) CRLF)
CRLF
[ message-body ]
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
*/ public class Response { private static final int BUFFER_SIZE = 1024;
Request request;
OutputStream output; public Response(OutputStream output) {
this.output = output;
} public void setRequest(Request request) {
this.request = request;
} public void sendStaticResource() throws IOException {
byte[] bytes = new byte[BUFFER_SIZE];
FileInputStream fis = null;
try {
System.out.println(HttpServer.WEB_ROOT+"  **** "+request.getUri());
File file = new File(HttpServer.WEB_ROOT, request.getUri()); //连接用户请求的"文件"
if (file.exists()) {
fis = new FileInputStream(file);
int ch = fis.read(bytes, 0, BUFFER_SIZE); //把文件中的东西读出来放到bytes字符数组里
while (ch!=-1) { //把bytes数组里的东西放到要给client回复的流里面
output.write(bytes, 0, ch);
ch = fis.read(bytes, 0, BUFFER_SIZE);
}
}
else { //要是文件不存在 不解释
// file not found
String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: 23\r\n" +
"\r\n" +
"<h1。File Not Found</h1。";
output.write(errorMessage.getBytes());
}
}
catch (Exception e) {
// thrown if cannot instantiate a File object
System.out.println(e.toString() );
}
finally {
if (fis!=null)
fis.close();
}
}
}

首先假设大家用的是Eclipse,那么没有不论什么问题,假设大家是用命令行的形式的话会存在一个问题,HttpServer与Response两个类相互依赖,先编译谁?

解决的方法 cd到三个类的文件夹 然后 javac *.java





等启动HttpServer后

在浏览器输入localhost:8080/index.html

显演示样例如以下

明确了吧 我们把index.html放到D:\尚学堂 j2ee\javase\尚学堂科技_马士兵_J2SE_5.0_第01章_JAVA简单介绍_源码_及重要说明\java\Socket\no\WebContent 文件夹下

index.html内容例如以下

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

我是index

</body>

</html>

再次请求 截图例如以下

大家一定非常奇怪,我为什么不用火狐或这个Chrome,找个EditPlus点过来点过去。

大家试试就知道了,火狐不知道由于什么原因,在地址栏敲回车后,会发出两次请求。

结果就是报错。

再试试http://localhost:8080/SHUTDOWN

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGxmMTIzMzIx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

程序退出

how tomcat works 读书笔记(一)----------一个简单的webserver的更多相关文章

  1. how tomcat works 读书笔记(二)----------一个简单的servlet容器

    app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...

  2. how tomcat works 读书笔记(一)----------一个简单的web服务器

    http协议 若是两个人能正常的说话交流,那么他们间必定有一套统一的语言规则<在网络上服务器与客户端能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertext tran ...

  3. how tomcat works 读书笔记四 tomcat的默认连接器

    事实上在第三章,就已经有了连接器的样子了,只是那仅仅是一个学习工具,在这一章我们会開始分析tomcat4里面的默认连接器. 连接器 Tomcat连接器必须满足下面几个要求 1 实现org.apache ...

  4. How Tomcat Works读书笔记三-------连接器

    几个概念 HttpServlet,Servlet Servlet是一个接口,定义了一种网络服务,我们所有的servlet都要实现它(或它的子类) HttpServlet是一个抽象类,它针对的就是htt ...

  5. how tomcat works读书笔记 七 日志记录器

    大家可以松一口气了,这个组件比较简单,这一节和前面几节想比,也简单的多. Logger接口 Tomcat中的日志记录器都必须实现org.apache.catalina.Logger接口. packag ...

  6. How tomcat works 读书笔记十七 启动tomcat 下

    在上一节中,我们程序的起始位置还是Bootstrap,现在我们通过bat文件来启动这个类. 在分析catalina.bat之前,我们先看看几个简单的我们能用到的dos命令. 基础知识 1 rem 注释 ...

  7. How tomcat works 读书笔记十五 Digester库 下

    在这一节里我们说说ContextConfig这个类. 这个类在很早的时候我们就已经使用了(之前那个叫SimpleContextConfig),但是在之前它干的事情都很简单,就是吧context里的co ...

  8. how tomcat works 读书笔记 十一 StandWrapper 上

    方法调用序列 下图展示了方法调用的协作图:  这个是前面第五章里,我画的图:  我们再回顾一下自从连接器里  connector.getContainer().invoke(request, resp ...

  9. How Tomcat Works 读书笔记 八 载入器 上

    Java的类载入器 详细资料见 http://blog.csdn.net/dlf123321/article/details/39957175 http://blog.csdn.net/dlf1233 ...

随机推荐

  1. jquery——zTree, 完美好用的树插件

    Demo 这绝对是我见过最完美的tree了,尽管是国产货,但一点不输国外产品,国外的还没有见过这么强的. _______________________________________________ ...

  2. [RxJS] Observables can complete

    The Observer object has the functions next() and error(). In this lesson we will see the other (and ...

  3. android学习——GestureDetector.OnGestureListener 详解

    Android Touch Screen 与传统Click Touch Screen不同,会有一些手势(Gesture),例如Fling,Scroll等等.这些Gesture会使用户体验大大提升.An ...

  4. PLSQL Developer安装(Oracle11g+win7_64bit)

    1)安装Oracle 11g 64位 2)安装32位的Oracle客户端( instantclient-basic-win32-11.2.0.1.0)下载地址:http://www.oracle.co ...

  5. vim的基本使用方法

    头记:vim作为被大多数程序员所推崇的编辑器,是源于它的自由灵活以及令人舒服的输入模式,但对于新手来说无疑是个噩梦(需要记太多的命令), 而作为使用了vim有一段时间的我来说,总结下常用的命令,以备新 ...

  6. 读取xml文件信息

    static void Main(string[] args) { XmlTextReader reader = new XmlTextReader(@"D:\zy\visual studi ...

  7. datagrid的基本操作-增删改

    1 ---恢复内容开始--- <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  8. ASP.NET MVC Controller接收ajax post方式发送过来的json对象或数组数据

    本例旨在说明我的一种Controller接收ajax提交(POST)过来的json对象或数组信息的方式,感觉应该有更好的方式,欢迎提出宝贵意见. JSON.stringify(jsonObj)不支持I ...

  9. sql练习总结(一)

    最近在学sql,遇到了这么一道题: 写出一条Sql语句:取出表A中第31到第40记录(SQLServer,以自动增长的ID作为主键,注意:ID可能不是连续的. 把所能想到的实现方法都做了一遍: 1.用 ...

  10. oracle数据库实验讲义-读书笔记(一)

    1.激活锁定的用户alter user scott account unlock identified by tiger;2.使用内含脚本建立scott用户@%oracle_home%\rdbms\a ...