概述
在Jetty中,使用Connector来抽象Jetty服务器对某个端口的监听。在Connector启动时,它会启动acceptors个Acceptor线程用于监听在Connector中配置的端口。对于客户端的每次连接,Connector都会创建相应的EndPoint来表示该连接,一般在创建EndPoint的同时会同时创建Connection,这里EndPoint用于和Socket打交道,而Connection用于在从Socket中读取到数据后的处理逻辑以及生成响应数据的处理逻辑。
不同的Connector会创建不同的EndPoint和Connection实例。如SocketConnector创建ConnectorEndPoint和HttpConnection,SslSocketConnector创建SslConnectorEndPoint和HttpConnection,SelectChannelConnector创建SelectChannelEndPoint和SelectChannelHttpConnection,SslSelectChannelConnector创建SslSelectChannelEndPoint和SelectChannelHttpConnection,BlockingChannelConnector创建BlockingChannelEndPoint和HttpConnection等。
EndPoint接口定义
Jetty中EndPoint接口定义如下:
public interface EndPoint {
//EndPoint是对一次客户端到服务器连接的抽象,每一个新的连接都会创建一个新的EndPoint,并且在这个EndPoint中包含这次连接的Socket。由于EndPoint包含底层的连接Socket,因而它主要用于处理从Socket中读取数据和向Socket中写入数据,即对应EndPoint接口中的fill和flush方法。//从Socket中读取数据,并写入Buffer中直到数据读取完成或putIndex到Buffer的capacity。返回总共读取的字节数。在实现中,StreamEndPoint使用Buffer直接从Socket的InputStream中读取数据,而ChannelEndPoint则向Channel读取数据到Buffer。 int fill(Buffer buffer) throws IOException;
//将Buffer中的数据(从getIndex到putIndex的数据)写入到Socket中,同时清除缓存(调用Buffer的clear方法)。在实现中,StreamEndPoint使用Buffer直接向Socket的OutputStream写入数据,而ChanelEndPoint则将Buffer中的数据写入Channel中。 int flush(Buffer buffer) throws IOException;
//类似上面的flush,它会将传入的header、buffer、trailer按顺序写入Socket中(OutputStream或者Channel)。返回总共写入的字节数。 int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException;
//当在处理HTTP/1.0请求时或当前Request中的KeepAlive的值为false时,在处理完成当前请求后,需要调用shutdownOutput()方法,关闭当前连接;或在处理当前请求时出现比较严重的错误、Socket超时时。在调用完shutdownOutput()方法后,isOutputShutdown()方法返回true。 void shutdownOutput() throws IOException;
boolean isOutputShutdown();
//当Server无法从当前连接(Socket)中读取数据时(即read返回-1)时,调用shutdownInput()方法以关闭当前连接,此时isInputShutdown()返回true。 void shutdownInput() throws IOException;
boolean isInputShutdown();
//当Socket超时或在读写Socket过程中出现任何IO错误时,Server会直接调用close()方法以关闭当前连接。 void close() throws IOException;
//当前Connection是否已经打开,对ChannelEndPoint来说表示Channel.isOpen()返回true,对SocketEndPoint来说,表示Socket没有被关闭。 public boolean isOpen();
//对StreamEndPoint来说,它的读写是阻塞式的,但是对ChannelEndPoint来说,如果它内部的channel是SelectableChannel,那么这个Channel的读写可以配置成非阻塞的(通过SelectableChannel.isBlocking()方法判断)。因而对SelectChannelEndPoint需要使用blockReadable()方法来阻塞直到超时。返回true表示阻塞读取失败,此时HttpParser会关闭这个EndPoint,并抛出异常。blockWritable()方法类似blockReadable()用于SelectChannelEndPoint以等待有数据写入到Channel中,如果返回false,表示在指定的时间内没有数据可写入Channel中(即超时),此时会关闭该EndPoint,并抛出异常。 public boolean isBlocking();
public boolean blockReadable(long millisecs) throws IOException