Tomcat请求处理(一) -- 服务器端口监听
其实tomcat在哪个类中监听请求的代码很容易找到:
在org.apache..JIoEndpoint$Acceptor#run()中的这么一句:
Socket socket = serverSocketFactory.acceptSocket(serverSocket);
可是ServerSocketFactory是个抽象类,我还是很想知道整个过程的来龙去脉的。
那就要还是从初始化开始,当Tomcat的HTTP Connector初始化,
org.apache.coyote.http11.Http11Protocol调用它的init()方法。
在这个init()方法中,又调用了org.apache..JIoEndpoint#init(),代码如下:
public void init() throws Exception {
if (initialized)
return;
// acceptor线程的数量
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
// 返回DefaultServerSocketFactory类对象做为ServerSocketFactory的实例
if (serverSocketFactory == null) {
serverSocketFactory = ServerSocketFactory.getDefault();
}
// 创建ServerSocket
if (serverSocket == null) {
try {
if (address == null) {
serverSocket = serverSocketFactory.createSocket(port, backlog); } else {
serverSocket = serverSocketFactory.createSocket(port, backlog, address);
}
} catch (BindException be) {
if (address == null)
throw new BindException(be.getMessage() + "<null>:" + port); else
throw new BindException(be.getMessage() + " " + address.toString() + ":" + port);
}
}
initialized = true;
}
现在已经知道了文章最初提到的serverSocketFactory引用的是一个
DefaultServerSocketFactory类的对象。并且在这里创建了一个ServerSocket对象。
当Tomcat初始化完毕,执行一系列开启服务的动作时,HTTP Connector也会执行它的start()方法,然后会调用Http11Protocol的start()方法,最后程序会执行到
JIoEndpoint#start(),下面来看一下:
public void start() throws Exception {
if (!initialized) {
init();
}
if (!running) {
running = true;
paused = false;
// 先初始化一些Worker
if (executor == null) {
workers = new WorkerStack(maxThreads);
}
// 开启Acceptor线程,默认只开启一个Acceptor线程,见
JIoEndpoint#init()。
for (int i = 0; i < acceptorThreadCount; i++) {
Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
acceptorThread.setPriority(threadPriority);
acceptorThread.setDaemon(daemon);
acceptorThread.start();
}
}
}
这样,就开启了一个Acceptor线程,接下来看一看这个线程做了什么东西。
public void run() {
while (running) {
while (paused) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
try {
// 开始监听端口
Socket socket = serverSocketFactory.acceptSocket(serverSocket); // 初始化Socket
serverSocketFactory.initSocket(socket);
if (!processSocket(socket)) {
try {
socket.close();
} catch (IOException e) {
}
}
} catch (IOException x) {
if (running)
log.error(sm.getString("endpoint.accept.fail"), x);
} catch (Throwable t) {
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
}
至此,Tomcat开启了一个端口进行请求的监听。
第二篇:Tomcat端口占用
假设80端口被占用
运行cmd,打开命令窗口,输入netstat -ano|findstr "8080"
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4
TCP 0.0.0.0:8009 0.0.0.0:0 LISTENING 3876 TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 3876 TCP 127.0.0.1:8080 127.0.0.1:1541 ESTABLISHED 2752
最后一栏PID
打开win任务管理,选择PID列为216的进程结束