本文在 nodelover.me 同步发布。
地址 http://nodelover.me/#/blog/article/info/589aa7f6b123db16a3b76934
基础要点
服务器编程,其实就是 Socket 编程,而 HTTP 请求是一种特殊的 Socket,要实现监听某一个端口接受请求,我们就必须要用到Java 的ServerSocket
类。
我们看一下它的构造器
public ServerSocket(
int port,
int backlog,
InetAddress bindAddr
) throws IOException
port
监听端口
backlog
监听队列长度
bindAddr
IP 地址
ServerSocket
有一个队列,存放还没有来得及处理的客户端Socket
,这个队列的容量就是backlog
的含义。
那么客户端的 socket
连接过来,我们如何拿到 socket
呢?
答案就是 accept
, 这个方法是在 ServerSocket
的实例上面。
public Socket accept() throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!isBound())
throw new SocketException("Socket is not bound yet");
Socket s = new Socket((SocketImpl) null);
implAccept(s);
return s;
}
accept
方法就是创建了一个空的 Socket
然后交给 implAccept
处理。
而 Socket 对象上面的 getInputStream
和 getOutputStream
方法就可以拿到相应的Stream
。
这里的 Input 可以理解为request
,而 Output 可以理解为 response
。
了解 Stream
的都知道,流就像一个管道,里面流的是二进制数据。假如我们想要得到我们人可以阅读的,还需要自己转换。
你好,Yugo
了解了这些之后,我们实现一个简单的 HelloWorld
就完成了。
import java.io.*;
import java.net.*;
public class test {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8080, 5, InetAddress.getByName("127.0.0.1"));
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
/**
* 打印 request 的信息
*/
byte[] buffer = new byte[2048];
StringBuffer info = new StringBuffer(2048);
int size = is.read(buffer);
for (int i = 0; i < size; i++) info.append((char) buffer[i]);
System.out.println(info);
/**
* 输出一些内容
*/
String message = "<h1>Hello Yugo</h1>";
os.write(message.getBytes());
}catch (Exception e){
e.printStackTrace();
}
}
}
这里会用到 IO,和 Net 包,IO 里面包含了 Stream 的输入输出流。而 Net 包里面包含了 Socket 类似的一些类。
🔓 运行
访问 localhost:8080 可以看到以下界面
控制台打印结果
这样的代码只能运行一次,因为我们只通过 accept
拿到了一个 socket
。
通常我们会把 accept
写到循环里面。
基础原理就这么多。
假如想实现成静态服务器,这需要不少封装,更多代码请移步到这里。