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的整个设计还是挺简练的。。。。

原创粉丝点击