jetty SocketEndPoint分析
来源:互联网 发布:深圳网络推广课程 编辑:程序博客网 时间:2024/06/06 04:36
这里endPoint的概念可以按字面来当成是端点吧,因为TCP通信是双工的,那么就存在着两个端点。。。
这里我们先来看看SocketEndPint的继承体系:
这个够简单的吧,这几就是直线型的,那么这里我们先来看看EndPoint接口的定义吧:
//端点的定义public interface EndPoint{ //关闭当前的端点 void close() throws IOException; //读取数据,然后将其保存到buffer里面,返回表示实际读取的字节数目,-1表示已经读完了 int fill(Buffer buffer) throws IOException; //将buffer里面的数据发送出去,返回实际发送的字节数目 int flush(Buffer buffer) throws IOException; //连续写? int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException; //返回当前的本地地址ip public String getLocalAddr(); //本地的主机名 public String getLocalHost(); //本地端口 public int getLocalPort(); //远程的ip地址 public String getRemoteAddr(); //远程的主机名字 public String getRemoteHost(); //远程的端口号 public int getRemotePort(); //是否是阻塞的 public boolean isBlocking(); //是否缓冲 public boolean isBufferred(); /* ------------------------------------------------------------ */ public boolean blockReadable(long millisecs) throws IOException; /* ------------------------------------------------------------ */ public boolean blockWritable(long millisecs) throws IOException; //是否已经打开 public boolean isOpen(); //返回底层的实现,是socket或者channel public Object getTransport(); //是否有缓存的输入数据 public boolean isBufferingInput(); //是否有缓存的输出数据 public boolean isBufferingOutput(); //将缓存的输出全部输出 public void flush() throws IOException; }
它主要定义了一些对数据操作的方法,例如flush和fill,其中flush将buffer通过底层发送出去,而fill用于从底层的连接读取数据,然后将其填充到buffer里面去。。。。
当然还有一些其他的方法,例如获取本地和远程的ip的地址什么的,不过总的来说还是很简单的。。。
那么接下来来看看StreamEndPoint的定义吧,它是一个抽象类,实现了EndPoint中的大多数方法:
//基于流的endPointpublic class StreamEndPoint implements EndPoint{ InputStream _in; //输入流 OutputStream _out; //输出流 //构造函数 public StreamEndPoint(InputStream in, OutputStream out) { _in=in; _out=out; } //是否是阻塞的,是 public boolean isBlocking(){ return true; } public boolean blockReadable(long millisecs) throws IOException { return true; } public boolean blockWritable(long millisecs) throws IOException { return true; } //是否已经打开 public boolean isOpen(){ return _in!=null; } //是否关闭 public final boolean isClosed() { return !isOpen(); } //关闭,说白了就是关闭底层的输入输出流 public void close() throws IOException { if (_in!=null) _in.close(); _in=null; if (_out!=null) _out.close(); _out=null; } //从inputstream中读取数据,存到buffer里面 public int fill(Buffer buffer) throws IOException { // TODO handle null array() if (_in==null) return 0; int space=buffer.space(); //当前buffer的空间 if (space<=0) { if (buffer.hasContent()) return 0; throw new IOException("FULL"); } int len = buffer.readFrom(_in,space); //读取,space为最大值 return len; } //将buffer里面的数据输出到outputstream public int flush(Buffer buffer) throws IOException { // TODO handle null array() if (_out==null) return -1; int length=buffer.length(); //当前buffer的自己数 if (length>0) buffer.writeTo(_out); buffer.clear(); return length; } //这里就姑且认为是连续写吧 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException { int len=0; if (header!=null) { int tw=header.length(); if (tw>0) { int f=flush(header); len=f; if (f<tw) return len; } } if (buffer!=null) { int tw=buffer.length(); if (tw>0) { int f=flush(buffer); if (f<0) return len>0?len:f; len+=f; if (f<tw) return len; } } if (trailer!=null) { int tw=trailer.length(); if (tw>0) { int f=flush(trailer); if (f<0) return len>0?len:f; len+=f; } } return len; } //获取本地的ip地址,这里其实要留给子类来具体的实现 public String getLocalAddr() { return null; } public String getLocalHost() { return null; } //获取本地的端口 public int getLocalPort() { return 0; } public String getRemoteAddr() { return null; } public String getRemoteHost() { return null; } public int getRemotePort() { return 0; } public Object getTransport() { return null; } public InputStream getInputStream() { return _in; } public void setInputStream(InputStream in) { _in=in; } public OutputStream getOutputStream() { return _out; } public void setOutputStream(OutputStream out) { _out=out; } public void flush() throws IOException { _out.flush(); } public boolean isBufferingInput() { return false; } public boolean isBufferingOutput() { return false; } public boolean isBufferred() { return false; }}
其实从类型的名字就能够看出,它是基于流的,那么它有两个属性inputStream和outputSteam就很正常了,那么它所实现的I/O操作都需要由他们来实现才可以。。。
而且上面具体的方法实现也都很简单,可以看看fill方法,无非就是从inputstream里读取数据然后保存到buffer里面。。。
那么最后我们来看看SocketEndPoint的定义吧:
public class SocketEndPoint extends StreamEndPoint{ Socket _socket; InetSocketAddress _local; //本地的地址 InetSocketAddress _remote; //远程地址 //构造函数 public SocketEndPoint(Socket socket) throws IOException { super(socket.getInputStream(),socket.getOutputStream()); _socket=socket; } //用于判断当前是否打开的,需要底层的socket打开的才表示打开的 public boolean isOpen() { return super.isOpen() && _socket!=null && !_socket.isClosed() && !_socket.isInputShutdown() && !_socket.isOutputShutdown(); } //说白了就是关闭底层的socket public void close() throws IOException { if (!_socket.isClosed() && !_socket.isOutputShutdown()) { try { _socket.shutdownOutput(); } catch(IOException e) { Log.ignore(e); } catch(UnsupportedOperationException e) { Log.ignore(e); } } _socket.close(); _in=null; _out=null; } //获取本地的地址 public String getLocalAddr() { if (_local==null) _local=(InetSocketAddress)_socket.getLocalSocketAddress(); if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress()) return Portable.ALL_INTERFACES; return _local.getAddress().getHostAddress(); } public String getLocalHost() { if (_local==null) _local=(InetSocketAddress)_socket.getLocalSocketAddress(); if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress()) return Portable.ALL_INTERFACES; return _local.getAddress().getCanonicalHostName(); } //返回本地端口 public int getLocalPort() { if (_local==null) _local=(InetSocketAddress)_socket.getLocalSocketAddress(); return _local.getPort(); } //返回远程的ip地址 public String getRemoteAddr() { if (_remote==null) _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); InetAddress addr = _remote.getAddress(); return ( addr == null ? null : addr.getHostAddress() ); } //返回远程的主机名 public String getRemoteHost() { if (_remote==null) _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); return _remote.getAddress().getCanonicalHostName(); } //返回远程的端口地址 public int getRemotePort() { if (_remote==null) _remote=(InetSocketAddress)_socket.getRemoteSocketAddress(); return _remote.getPort(); } //返回底层用于通信的socket public Object getTransport() { return _socket; }}
这个类从名字也都能看出个大概了,底层的连接用的是socket,那么父类中的stream直接从socket中获取就可以了,然后还是先了一些其他的方法,例如获取本地和远程的地址什么的。。。
看到这里觉得jetty的整个设计还是挺简练的。。。。
- jetty SocketEndPoint分析
- Jetty之SocketEndPoint分析
- Jetty之SocketEndPoint分析
- Jetty分析
- Jetty 分析
- Jetty 源码分析
- Jetty 源码分析(转移)
- Jetty 源码分析
- Jetty 源码分析
- jetty 源码分析
- Jetty 源码分析
- Jetty 源码分析
- Jetty 源码分析
- Jetty 源码分析
- Jetty 源码分析
- Jetty 服务器架构分析
- Jetty 源码分析
- Jetty 源码分析
- 如何根据异常提示信息找出程序出错代码(VC6) (carefull)
- 动态库与静态库的异同、生成和使用详解
- centos 6.4 server 安装nginx
- Unity3D研究院之FBX模型的载入与人物行走动画的播放
- 如何在网页中插入关键词
- jetty SocketEndPoint分析
- java防止SQL注入的几个途径
- Python字典赋值到JavaScript变量
- NTP时间服务器
- 疑问
- Android 使用Parcelable序列化对象
- hadoop深入了解
- 黑马程序员-------.net基础知识八
- Android开发实现qqminihd 左右滑动菜单效果