文章目录代码仓库https://gitee.com/cyfuture/how-tomcat-work
- socket
- ServerSocket
- HttpServer
在 Java 里边,套接字指的是 java.net.Socket 类。要创建一个套接字,你可以使用 Socket 类众多构造方法中的一个。其中一个接收主机名称 host和端口号port
public Socket (java.lang.String host, int port)
在这里主机是指要连接的远程机器名称或者 IP 地址,端口是指远程应用的端口号。例如,要连接本机的 80 端口,你需要构造以下的 Socket 对象: new Socket (“127.0.0.1”, 80);
一旦你成功创建了一个 Socket 类的实例,你可以使用它来发送和接受字节流。
发送数据
要发送字节流,你首先必须调用Socket 类的 getOutputStream 方法来获取一个 java.io.OutputStream 对象。
要 发 送 文 本 到 一 个 远 程 应 用 , 你 经 常 要 从 返 回 的 OutputStream 对 象 中 构 造 一 个 java.io.PrintWriter 对象。通过PrintWriter发送纯文本更方便
接收数据
要从连接的另一端接受字节流,你可以调用 Socket 类的 getInputStream 方法用来返回一个 java.io.InputStream 对象。
public class TCPClient {
public static void main(String[] args) throws IOException {
//可能会出现的异常java.net.ConnectException: Connection refused
Socket socket = new Socket("127.0.0.1",8888);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello".getBytes());
outputStream.close();
}
}
ServerSocket
Socket 类代表一个客户端套接字,即任何时候你想连接到一个远程服务器应用的时候你构 造的套接字.
服务器的套接字和客户端的不同,因为你的服务器必须随时待命,因为它不知道一个客户端应用什么时 候会尝试去连接它。为了让你的服务器应用能随时待命,你需要使用 java.net.ServerSocket 类
ServerSocket 和 Socket 不同,服务器套接字的角色是等待来自客户端的连接请求。一旦服 务器套接字获得一个连接请求,它创建一个 Socket 实例来与客户端进行通信。 要创建一个服务器套接字,你需要使用 ServerSocket 类提供的四个构造方法中的一个。你需要指定 IP 地址和服务器套接字将要进行监听的端口号。
通常,IP 地址将会是 127.0.0.1,也就是说,服务器套接字将会监听本地机器。服务器套接字正在监听的 IP 地址被称为是绑定地址。
服务器套接字的另一个重要的属性是 backlog,这是服务器套接字开始拒绝传入的请求之前,传 入的连接请求的最大队列长度。
其中一个 ServerSocket 类的构造方法如下所示
public ServerSocket(int port, int backLog, InetAddress bindingAddress);
对于这个构造方法,绑定地址必须是 java.net.InetAddress 的一个实例。
一种构造 InetAddress 对象的简单的方法是调用它的静态方法 getByName,传入一个包含主机名称的字符 串,就像下面的代码一样. InetAddress.getByName(“127.0.0.1”);
下面一行代码构造了一个监听的本地机器 8080 端口的 ServerSocket,它的 backlog 为 1。
new ServerSocket(8080, 1, InetAddress.getByName(“127.0.0.1”));
这个ServerSocket 实例会监听本机的8080端口,等待客户端的连接请求。
获取客户端的连接请求通过调用 ServerSocket 类的 accept 方法。这个方法只 会在有连接请求时才会返回,并且返回值是一个 Socket 类的实例。Socket 对象接下去可以发送字节流到客户端,也能从客户端应用中接受字节流。
public class TCPServer {
public static void main(String[] args) throws IOException {
//服务器启动后会在这等待客户端的连接
ServerSocket server = new ServerSocket(8888);
//这个方法会阻塞,直到有客户端连接
Socket accept = server.accept();
InputStream inputStream = accept.getInputStream();
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
System.out.println(new String(bytes,0,len));
inputStream.close();
}
}
HttpServer
接下来,我通过ServerSocket 包装一个类HttpServer
详细代码在我的仓库cy/HowTomcatWork (gitee.com)
public class HttpServer {
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 = 8090;
try {
serverSocket = new ServerSocket(port, 10, InetAddress.getByName("127.0.0.1"));
}
catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
// Loop waiting for a request
while (!shutdown) {
Socket socket = null;
InputStream input = null;
OutputStream output = null;
try {
socket = serverSocket.accept();
input = socket.getInputStream(); //使用input得到客户端发送来的数据
output = socket.getOutputStream();//使用output向客户端发送数据
// create Request object and parse
Request request = new Request(input);
request.parse();
// 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;
}
}
}
}
web 服务器能提供公共静态 final 变量 WEB_ROOT 所在的目录和它下面所有的子目录下的静 态资源。如下所示,WEB_ROOT 被初始化
public static final String WEB_ROOT = System.getProperty(“user.dir”) + File.separator + “webroot”;
代码列表包括一个叫 webroot 的目录,包含了一些你可以用来测试这个应用程序的静态资源。 为了请求一个静态资源,在你的浏览器的地址栏或者网址框里边敲入以下的 URL:
http://machineName:port/staticResource
如果你要从一个不同的机器上发送请求到你的应用程序正在运行的机器上,machineName 应 该是正在运行应用程序的机器的名称或者 IP 地址。
假如你的浏览器在同一台机器上,你可以使 用 localhost 作为 machineName。端口是 8080,staticResource 是你需要请求的文件的名称, 且必须位于 WEB_ROOT 里边。
举例来说,假如你正在使用同一台计算机上测试应用程序,并且你想要调用 HttpServer 对 象去发送一个 index.html 文件,你可以使用一下的 URL: http://localhost:8080/index.html
要停止服务器,使用下面的 URL: http://localhost:8080/SHUTDOWN



