客户端和服务器之间的链接建立了,那接下来就要接受数据,处理请求,我们来看看是怎样实现的。
1、我们之前创建了Acceptor线程类接受连接,成功连接以后就要进行处理socket了。
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
int errorDelay = 0;
while (running) {
while (paused && running) {
state = AcceptorState.PAUSED;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
if (!running) {
break;
}
state = AcceptorState.RUNNING;
try {
countUpOrAwaitConnection();
Socket socket = null;
try {
socket = serverSocketFactory.acceptSocket(serverSocket);
} catch (IOException ioe) {
errorDelay = handleExceptionWithDelay(errorDelay);
throw ioe;
}
errorDelay = 0;
if (running && !paused && setSocketOptions(socket)) {
// 在这里处理请求
if (!processSocket(socket)) {
closeSocket(socket);
}
} else {
closeSocket(socket);
}
} catch (IOException x) {
if (running) {
log.error(sm.getString("endpoint.accept.fail"), x);
}
} catch (NullPointerException npe) {
if (running) {
log.error(sm.getString("endpoint.accept.fail"), npe);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
state = AcceptorState.ENDED;
}
}
protected class SocketProcessor implements Runnable {
// 包装socket
protected SocketWrapper<Socket> socket = null;
protected SocketStatus status = null;
public SocketProcessor(SocketWrapper<Socket> socket) {
if (socket == null) throw new NullPointerException();
this.socket = socket;
}
public SocketProcessor(SocketWrapper<Socket> socket, SocketStatus status) {
this(socket);
this.status = status;
}
@Override
public void run() {
boolean launch = false;
synchronized (socket) {
try {
SocketState state = SocketState.OPEN;
try {
serverSocketFactory.handshake(socket.getSocket());
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (log.isDebugEnabled()) {
log.debug(sm.getString("endpoint.err.handshake"), t);
}
state = SocketState.CLOSED;
}
if ((state != SocketState.CLOSED)) {
if (status == null) {
// 处理请求的方法
state = handler.process(socket, SocketStatus.OPEN);
} else {
state = handler.process(socket, status);
}
}
if (state == SocketState.CLOSED) {
if (log.isTraceEnabled()) {
log.trace("Closing socket:" + socket);
}
countDownConnection();
try {
socket.getSocket().close();
} catch (IOException e) {
}
} else if (state == SocketState.OPEN) {
socket.setKeptAlive(true);
socket.access();
launch = true;
} else if (state == SocketState.LONG) {
socket.access();
waitingRequests.add(socket);
}
} finally {
if (launch) {
try {
getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN));
} catch (NullPointerException npe) {
if (running) {
log.error(sm.getString("endpoint.launch.fail"), npe);
}
}
}
}
}
socket = null;
}
}
3、进入process方法
public SocketState process(SocketWrapper<S> socket, SocketStatus status) {
P processor = connections.remove(socket.getSocket());
if (getLog().isDebugEnabled()) {
getLog().debug("process() entry " +
"Socket: [" + logHashcode(socket.getSocket()) + "], " +
"Processor [" + logHashcode(processor) + "]");
}
socket.setAsync(false);
try {
if (processor == null) {
processor = recycledProcessors.poll();
}
if (processor == null) {
// 创建Http请求处理器
processor = createProcessor();
}
if (getLog().isDebugEnabled()) {
getLog().debug("process() gotProcessor " +
"Socket: [" + logHashcode(socket.getSocket()) + "], " +
"Processor [" + logHashcode(processor) + "]");
}
initSsl(socket, processor);
SocketState state = SocketState.CLOSED;
do {
if (processor.isAsync() || state == SocketState.ASYNC_END) {
state = processor.asyncDispatch(status);
if (getLog().isDebugEnabled()) {
getLog().debug("process() asyncDispatch " +
"Socket: [" + logHashcode(socket.getSocket()) + "], " +
"Processor: [" + logHashcode(processor) + "], " +
"State: [" + state.toString() + "]");
}
} else if (processor.isComet()) {
state = processor.event(status);
if (getLog().isDebugEnabled()) {
getLog().debug("process() event " +
"Socket: [" + logHashcode(socket.getSocket()) + "], " +
"Processor: [" + logHashcode(processor) + "], " +
"State: [" + state.toString() + "]");
}
} else {
// 同步处理socket
state = processor.process(socket);
if (getLog().isDebugEnabled()) {
getLog().debug("process() process " +
"Socket: [" + logHashcode(socket.getSocket()) + "], " +
"Processor: [" + logHashcode(processor) + "], " +
"State: [" + state.toString() + "]");
}
}
if (state != SocketState.CLOSED && processor.isAsync()) {
state = processor.asyncPostProcess();
if (getLog().isDebugEnabled()) {
getLog().debug("process() asyncPostProcess " +
"Socket: [" + logHashcode(socket.getSocket()) + "], " +
"Processor: [" + logHashcode(processor) + "], " +
"State: [" + state.toString() + "]");
}
}
} while (state == SocketState.ASYNC_END);
if (state == SocketState.LONG) {
longPoll(socket, processor);
} else if (state == SocketState.OPEN) {
release(socket, processor, false, true);
} else if (state == SocketState.SENDFILE) {
release(socket, processor, false, false);
} else {
release(socket, processor, true, false);
}
return state;
} catch (java.net.SocketException e) {
getLog().debug(sm.getString("ajpprotocol.proto.socketexception.debug"), e);
} catch (java.io.IOException e) {
getLog().debug(sm.getString("ajpprotocol.proto.ioexception.debug"), e);
}
catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
getLog().error(sm.getString("ajpprotocol.proto.error"), e);
}
release(socket, processor, true, false);
return SocketState.CLOSED;
}
4、在process方法中,解析成Request对象,交给CoyoteAdapter 进行处理
@Override
public SocketState process(SocketWrapper<S> socketWrapper) throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
setSocketWrapper(socketWrapper);
getInputBuffer().init(socketWrapper, endpoint);
getOutputBuffer().init(socketWrapper, endpoint);
error = false;
keepAlive = true;
comet = false;
openSocket = false;
sendfileInProgress = false;
readComplete = true;
if (endpoint.getUsePolling()) {
keptAlive = false;
} else {
keptAlive = socketWrapper.isKeptAlive();
}
if (disableKeepAlive()) {
socketWrapper.setKeepAliveLeft(0);
}
while (!error && keepAlive && !comet && !isAsync() &&
!endpoint.isPaused()) {
try {
setRequestLineReadTimeout();
if (!getInputBuffer().parseRequestLine(keptAlive)) {
if (handleIncompleteRequestLineRead()) {
break;
}
}
if (endpoint.isPaused()) {
response.setStatus(503);
error = true;
} else {
request.setStartTime(System.currentTimeMillis());
keptAlive = true;
if (!getInputBuffer().parseHeaders()) {
openSocket = true;
readComplete = false;
break;
}
if (!disableUploadTimeout) {
setSocketTimeout(connectionUploadTimeout);
}
}
} catch (IOException e) {
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("http11processor.header.parse"), e);
}
error = true;
break;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("http11processor.header.parse"), t);
}
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
if (!error) {
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("http11processor.request.prepare"), t);
}
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
}
if (maxKeepAliveRequests == 1) {
keepAlive = false;
} else if (maxKeepAliveRequests > 0 &&
socketWrapper.decrementKeepAlive() <= 0) {
keepAlive = false;
}
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
// 把请求交给CoyoteAdapter 来处理
adapter.service(request, response);
if (keepAlive && !error) {
error = response.getErrorException() != null || (!isAsync() && statusDropsConnection(response.getStatus()));
}
setCometTimeouts(socketWrapper);
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
getLog().error(sm.getString("http11processor.request.process"), t);
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync() && !comet) {
if (error) {
getInputBuffer().setSwallowInput(false);
}
endRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
if (error) {
response.setStatus(500);
}
request.updateCounters();
if (!isAsync() && !comet || error) {
getInputBuffer().nextRequest();
getOutputBuffer().nextRequest();
}
if (!disableUploadTimeout) {
setSocketTimeout(endpoint.getSoTimeout());
}
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
if (breakKeepAliveLoop(socketWrapper)) {
break;
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (error || endpoint.isPaused()) {
return SocketState.CLOSED;
} else if (isAsync() || comet) {
return SocketState.LONG;
} else {
if (sendfileInProgress) {
return SocketState.SENDFILE;
} else {
if (openSocket) {
if (readComplete) {
return SocketState.OPEN;
} else {
return SocketState.LONG;
}
} else {
return SocketState.CLOSED;
}
}
}
}
5、CoyoteAdapter 的service方法继续解析请求
@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
request = connector.createRequest();
request.setCoyoteRequest(req);
response = connector.createResponse();
response.setCoyoteResponse(res);
request.setResponse(response);
response.setRequest(request);
req.setNote(ADAPTER_NOTES, request);
res.setNote(ADAPTER_NOTES, response);
req.getParameters().setQueryStringEncoding
(connector.getURIEncoding());
}
if (connector.getXpoweredBy()) {
response.addHeader("X-Powered-By", POWERED_BY);
}
boolean comet = false;
boolean async = false;
try {
req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
// 解析请求
boolean postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());
// 处理请求
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
if (request.isComet()) {
if (!response.isClosed() && !response.isError()) {
if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {
if (event(req, res, SocketStatus.OPEN)) {
comet = true;
res.action(ActionCode.COMET_BEGIN, null);
}
} else {
comet = true;
res.action(ActionCode.COMET_BEGIN, null);
}
} else {
request.setFilterChain(null);
}
}
}
AsyncContextImpl asyncConImpl = (AsyncContextImpl) request.getAsyncContext();
if (asyncConImpl != null) {
async = true;
} else if (!comet) {
request.finishRequest();
response.finishResponse();
if (postParseSuccess && request.getMappingData().context != null) {
((Context) request.getMappingData().context).logAccess(request, response, System.currentTimeMillis() - req.getStartTime(), false);
}
req.action(ActionCode.POST_REQUEST, null);
}
} catch (IOException e) {
} finally {
req.getRequestProcessor().setWorkerThreadName(null);
if (!comet && !async) {
request.recycle();
response.recycle();
} else {
request.clearEncoders();
response.clearEncoders();
}
}
}
protected boolean postParseRequest(org.apache.coyote.Request req, Request request, org.apache.coyote.Response res, Response response) throws Exception {
if (!req.scheme().isNull()) {
request.setSecure(req.scheme().equals("https"));
} else {
req.scheme().setString(connector.getScheme());
request.setSecure(connector.getSecure());
}
String proxyName = connector.getProxyName();
int proxyPort = connector.getProxyPort();
if (proxyPort != 0) {
req.setServerPort(proxyPort);
}
if (proxyName != null) {
req.serverName().setString(proxyName);
}
MessageBytes decodedURI = req.decodedURI();
decodedURI.duplicate(req.requestURI());
parsePathParameters(req, request);
try {
req.getURLDecoder().convert(decodedURI, false);
} catch (IOException ioe) {
res.setStatus(400);
res.setMessage("Invalid URI: " + ioe.getMessage());
connector.getService().getContainer().logAccess(request, response, 0, true);
return false;
}
if (!normalize(req.decodedURI())) {
res.setStatus(400);
res.setMessage("Invalid URI");
connector.getService().getContainer().logAccess(request, response, 0, true);
return false;
}
convertURI(decodedURI, request);
if (!checkNormalize(req.decodedURI())) {
res.setStatus(400);
res.setMessage("Invalid URI character encoding");
connector.getService().getContainer().logAccess(request, response, 0, true);
return false;
}
String principal = req.getRemoteUser().toString();
if (principal != null) {
request.setUserPrincipal(new CoyotePrincipal(principal));
}
String authtype = req.getAuthType().toString();
if (authtype != null) {
request.setAuthType(authtype);
}
MessageBytes serverName;
if (connector.getUseIPVHosts()) {
serverName = req.localName();
if (serverName.isNull()) {
res.action(ActionCode.REQ_LOCAL_NAME_ATTRIBUTE, null);
}
} else {
serverName = req.serverName();
}
if (request.isAsyncStarted()) {
request.getMappingData().recycle();
}
boolean mapRequired = true;
String version = null;
while (mapRequired) {
if (version != null) {
mapRequired = false;
}
connector.getMapper().map(serverName, decodedURI, version,
request.getMappingData());
request.setContext((Context) request.getMappingData().context);
request.setWrapper((Wrapper) request.getMappingData().wrapper);
if (request.getMappingData().contexts == null) {
mapRequired = false;
}
if (request.getContext() == null) {
res.setStatus(404);
res.setMessage("Not found");
Host host = request.getHost();
if (host != null) {
host.logAccess(request, response, 0, true);
}
return false;
}
String sessionID = null;
if (request.getServletContext().getEffectiveSessionTrackingModes()
.contains(SessionTrackingMode.URL)) {
sessionID = request.getPathParameter(
SessionConfig.getSessionUriParamName(
request.getContext()));
if (sessionID != null) {
request.setRequestedSessionId(sessionID);
request.setRequestedSessionURL(true);
}
}
parseSessionCookiesId(req, request);
parseSessionSslId(request);
sessionID = request.getRequestedSessionId();
if (mapRequired) {
if (sessionID == null) {
mapRequired = false;
} else {
Object[] objs = request.getMappingData().contexts;
for (int i = (objs.length); i > 0; i--) {
Context ctxt = (Context) objs[i - 1];
if (ctxt.getManager().findSession(sessionID) != null) {
if (ctxt.equals(request.getMappingData().context)) {
mapRequired = false;
} else {
version = ctxt.getWebappVersion();
request.getMappingData().recycle();
break;
}
}
}
if (version == null) {
mapRequired = false;
}
}
}
}
MessageBytes redirectPathMB = request.getMappingData().redirectPath;
if (!redirectPathMB.isNull()) {
String redirectPath = urlEncoder.encode(redirectPathMB.toString());
String query = request.getQueryString();
if (request.isRequestedSessionIdFromURL()) {
redirectPath = redirectPath + ";" +
SessionConfig.getSessionUriParamName(
request.getContext()) +
"=" + request.getRequestedSessionId();
}
if (query != null) {
redirectPath = redirectPath + "?" + query;
}
response.sendRedirect(redirectPath);
request.getContext().logAccess(request, response, 0, true);
return false;
}
if (!connector.getAllowTrace()
&& req.method().equalsIgnoreCase("TRACE")) {
Wrapper wrapper = request.getWrapper();
String header = null;
if (wrapper != null) {
String[] methods = wrapper.getServletMethods();
if (methods != null) {
for (int i = 0; i < methods.length; i++) {
if ("TRACE".equals(methods[i])) {
continue;
}
if (header == null) {
header = methods[i];
} else {
header += ", " + methods[i];
}
}
}
}
res.setStatus(405);
res.addHeader("Allow", header);
res.setMessage("TRACE method is not allowed");
request.getContext().logAccess(request, response, 0, true);
return false;
}
return true;
}
终于看到真正处理请求的方法了。。。。