Jetty之SocketEndPoint分析

来源:互联网 发布:egd网络小黄金骗局 编辑:程序博客网 时间:2024/06/03 13:54

这里Endpoint的概念可以按字面来当成是端点吧,因为TCP通信是双工的,那么就存在着两个端点。。。

这里我们先来看看SocketEndPint的继承体系:



这个够简单的吧,这几就是直线型的,那么这里我们先来看看EndPoint接口的定义吧:

[java] view plaincopy


  1. //端点的定义  
  2. public interface EndPoint  
  3. {  
  4.       
  5.     //关闭当前的端点  
  6.     void close() throws IOException;  
  7.   
  8.   
  9.     //读取数据,然后将其保存到buffer里面,返回表示实际读取的字节数目,-1表示已经读完了  
  10.     int fill(Buffer buffer) throws IOException;  
  11.       
  12.     //将buffer里面的数据发送出去,返回实际发送的字节数目  
  13.     int flush(Buffer buffer) throws IOException;  
  14.     //连续写?  
  15.     int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException;  
  16.   
  17.     //返回当前的本地地址ip  
  18.     public String getLocalAddr();  
  19.       
  20.     //本地的主机名  
  21.     public String getLocalHost();  
  22.   
  23.     //本地端口  
  24.     public int getLocalPort();  
  25.     //远程的ip地址  
  26.     public String getRemoteAddr();  
  27.     //远程的主机名字  
  28.     public String getRemoteHost();  
  29.     //远程的端口号  
  30.     public int getRemotePort();  
  31.     //是否是阻塞的  
  32.     public boolean isBlocking();  
  33.     //是否缓冲  
  34.     public boolean isBufferred();  
  35.       
  36.     /* ———————————————————— */  
  37.     public boolean blockReadable(long millisecs) throws IOException;  
  38.   
  39.     /* ———————————————————— */  
  40.     public boolean blockWritable(long millisecs) throws IOException;  
  41.   
  42.     //是否已经打开  
  43.     public boolean isOpen();  
  44.   
  45.     //返回底层的实现,是socket或者channel  
  46.     public Object getTransport();  
  47.       
  48.     //是否有缓存的输入数据  
  49.     public boolean isBufferingInput();  
  50.       
  51.     //是否有缓存的输出数据  
  52.     public boolean isBufferingOutput();  
  53.       
  54.     //将缓存的输出全部输出  
  55.     public void flush() throws IOException;  
  56.       
  57. }  

它主要定义了一些对数据操作的方法,例如flush和fill,其中flush将buffer通过底层发送出去,而fill用于从底层的连接读取数据,然后将其填充到buffer里面去。。。。

当然还有一些其他的方法,例如获取本地和远程的ip的地址什么的,不过总的来说还是很简单的。。。

那么接下来来看看StreamEndPoint的定义吧,它是一个抽象类,实现了EndPoint中的大多数方法:

[java] view plaincopy


  1. //基于流的endPoint  
  2. public class StreamEndPoint implements EndPoint  
  3. {  
  4.     InputStream _in;   //输入流  
  5.     OutputStream _out;  //输出流  
  6.     //构造函数  
  7.     public StreamEndPoint(InputStream in, OutputStream out) {  
  8.         _in=in;  
  9.         _out=out;  
  10.     }  
  11.     //是否是阻塞的,是  
  12.     public boolean isBlocking(){  
  13.         return true;  
  14.     }  
  15.   
  16.     public boolean blockReadable(long millisecs) throws IOException {  
  17.         return true;  
  18.     }  
  19.       
  20.     public boolean blockWritable(long millisecs) throws IOException {  
  21.         return true;  
  22.     }  
  23.   
  24.     //是否已经打开  
  25.     public boolean isOpen(){  
  26.         return _in!=null;  
  27.     }  
  28.   
  29.     //是否关闭  
  30.     public final boolean isClosed() {  
  31.         return !isOpen();  
  32.     }  
  33.   
  34.     //关闭,说白了就是关闭底层的输入输出流  
  35.     public void close() throws IOException  {  
  36.         if (_in!=null)  
  37.             _in.close();  
  38.         _in=null;  
  39.         if (_out!=null)  
  40.             _out.close();  
  41.         _out=null;  
  42.     }  
  43.   
  44.     //从inputstream中读取数据,存到buffer里面  
  45.     public int fill(Buffer buffer) throws IOException {  
  46.         // TODO handle null array()  
  47.         if (_in==null)  
  48.             return 0;  
  49.               
  50.         int space=buffer.space();  //当前buffer的空间  
  51.         if (space<=0)  
  52.         {  
  53.             if (buffer.hasContent())  
  54.                 return 0;  
  55.             throw new IOException(“FULL”);  
  56.         }  
  57.           
  58.         int len = buffer.readFrom(_in,space);  //读取,space为最大值  
  59.       
  60.         return len;  
  61.     }  
  62.   
  63.     //将buffer里面的数据输出到outputstream  
  64.     public int flush(Buffer buffer) throws IOException {  
  65.         // TODO handle null array()  
  66.         if (_out==null)  
  67.             return -1;  
  68.         int length=buffer.length();  //当前buffer的自己数  
  69.         if (length>0)  
  70.             buffer.writeTo(_out);  
  71.         buffer.clear();  
  72.         return length;  
  73.     }  
  74.     //这里就姑且认为是连续写吧  
  75.     public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException {  
  76.         int len=0;  
  77.         if (header!=null)  
  78.         {  
  79.             int tw=header.length();  
  80.             if (tw>0)  
  81.             {  
  82.                 int f=flush(header);  
  83.                 len=f;  
  84.                 if (f<tw)  
  85.                     return len;  
  86.             }  
  87.         }  
  88.           
  89.         if (buffer!=null)  
  90.         {  
  91.             int tw=buffer.length();  
  92.             if (tw>0)  
  93.             {  
  94.                 int f=flush(buffer);  
  95.                 if (f<0)  
  96.                     return len>0?len:f;  
  97.                 len+=f;  
  98.                 if (f<tw)  
  99.                     return len;  
  100.             }  
  101.         }  
  102.           
  103.         if (trailer!=null)  
  104.         {  
  105.             int tw=trailer.length();  
  106.             if (tw>0)  
  107.             {  
  108.                 int f=flush(trailer);  
  109.                 if (f<0)  
  110.                     return len>0?len:f;  
  111.                 len+=f;  
  112.             }  
  113.         }  
  114.         return len;  
  115.     }  
  116.     //获取本地的ip地址,这里其实要留给子类来具体的实现  
  117.     public String getLocalAddr() {  
  118.         return null;  
  119.     }  
  120.     public String getLocalHost() {  
  121.         return null;  
  122.     }  
  123.     //获取本地的端口  
  124.     public int getLocalPort() {  
  125.         return 0;  
  126.     }  
  127.     public String getRemoteAddr() {  
  128.         return null;  
  129.     }  
  130.   
  131.     public String getRemoteHost() {  
  132.         return null;  
  133.     }  
  134.     public int getRemotePort() {  
  135.         return 0;  
  136.     }  
  137.   
  138.     public Object getTransport() {  
  139.         return null;  
  140.     }  
  141.     public InputStream getInputStream() {  
  142.         return _in;  
  143.     }  
  144.     public void setInputStream(InputStream in) {  
  145.         _in=in;  
  146.     }  
  147.     public OutputStream getOutputStream() {  
  148.         return _out;  
  149.     }  
  150.     public void setOutputStream(OutputStream out) {  
  151.         _out=out;  
  152.     }  
  153.   
  154.     public void flush() throws IOException {     
  155.         _out.flush();  
  156.     }  
  157.   
  158.     public boolean isBufferingInput() {  
  159.         return false;  
  160.     }  
  161.   
  162.     public boolean isBufferingOutput() {  
  163.         return false;  
  164.     }  
  165.   
  166.     public boolean isBufferred() {  
  167.         return false;  
  168.     }  
  169.   
  170. }  

其实从类型的名字就能够看出,它是基于流的,那么它有两个属性inputStream和outputSteam就很正常了,那么它所实现的I/O操作都需要由他们来实现才可以。。。

而且上面具体的方法实现也都很简单,可以看看fill方法,无非就是从inputstream里读取数据然后保存到buffer里面。。。

那么最后我们来看看SocketEndPoint的定义吧:

[java] view plaincopy


  1. public class SocketEndPoint extends StreamEndPoint  
  2. {  
  3.     Socket _socket;  
  4.     InetSocketAddress _local;   //本地的地址  
  5.     InetSocketAddress _remote;   //远程地址  
  6.     //构造函数  
  7.     public SocketEndPoint(Socket socket)  
  8.         throws IOException    {  
  9.         super(socket.getInputStream(),socket.getOutputStream());  
  10.         _socket=socket;  
  11.     }  
  12.   
  13.     //用于判断当前是否打开的,需要底层的socket打开的才表示打开的  
  14.     public boolean isOpen() {  
  15.         return super.isOpen() && _socket!=null && !_socket.isClosed() && !_socket.isInputShutdown() && !_socket.isOutputShutdown();  
  16.     }  
  17.   
  18.     //说白了就是关闭底层的socket  
  19.     public void close() throws IOException {  
  20.         if (!_socket.isClosed() && !_socket.isOutputShutdown()) {  
  21.             try {  
  22.                 _socket.shutdownOutput();  
  23.             }  
  24.             catch(IOException e) {  
  25.                 Log.ignore(e);  
  26.             }  
  27.             catch(UnsupportedOperationException e) {  
  28.                 Log.ignore(e);  
  29.             }  
  30.         }  
  31.         _socket.close();  
  32.         _in=null;  
  33.         _out=null;  
  34.           
  35.     }  
  36.     //获取本地的地址  
  37.     public String getLocalAddr() {  
  38.         if (_local==null)  
  39.             _local=(InetSocketAddress)_socket.getLocalSocketAddress();  
  40.           
  41.        if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())  
  42.            return Portable.ALL_INTERFACES;  
  43.           
  44.         return _local.getAddress().getHostAddress();  
  45.     }  
  46.   
  47.   
  48.     public String getLocalHost() {  
  49.         if (_local==null)  
  50.             _local=(InetSocketAddress)_socket.getLocalSocketAddress();  
  51.           
  52.        if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())  
  53.            return Portable.ALL_INTERFACES;  
  54.           
  55.         return _local.getAddress().getCanonicalHostName();  
  56.     }  
  57.   
  58.     //返回本地端口  
  59.     public int getLocalPort() {  
  60.         if (_local==null)  
  61.             _local=(InetSocketAddress)_socket.getLocalSocketAddress();  
  62.         return _local.getPort();  
  63.     }  
  64.   
  65.     //返回远程的ip地址  
  66.     public String getRemoteAddr() {  
  67.         if (_remote==null)  
  68.             _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();  
  69.           
  70.         InetAddress addr = _remote.getAddress();  
  71.         return ( addr == null ? null : addr.getHostAddress() );  
  72.     }  
  73.   
  74.     //返回远程的主机名  
  75.     public String getRemoteHost()  {  
  76.         if (_remote==null)  
  77.             _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();  
  78.           
  79.         return _remote.getAddress().getCanonicalHostName();  
  80.     }  
  81.   
  82.     //返回远程的端口地址  
  83.     public int getRemotePort() {  
  84.         if (_remote==null)  
  85.             _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();  
  86.         return _remote.getPort();  
  87.     }  
  88.   
  89.     //返回底层用于通信的socket  
  90.     public Object getTransport() {  
  91.         return _socket;  
  92.     }  
  93. }  

这个类从名字也都能看出个大概了,底层的连接用的是socket,那么父类中的stream直接从socket中获取就可以了,然后还是先了一些其他的方法,例如获取本地和远程的地址什么的。。。


看到这里觉得jetty的整个设计还是挺简练的。。。。

0 0