已阅读5页,还剩13页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
核心功能支持面向流通信主要抽象是Connection接口。通过IBlockingConnection或者INonblockingConnection对象进行数据的读写。在record或者bulk状态中,Connection对象提供了对于特定数据类型的几个方便方法。Connection实现了java.nio包中的GatheringByteChannel和WritableByteChannel接口,如果InputStream或者OutputStream对象被需要,可以使用java.nio.Channels.newInputStream()和java.nio.Channels.newOutputStream()包装channel对象,因为经典的流只有在IBlockingConnection映射到经典的InputStream中时才有阻塞行为。提供的其他类型方法主要是控制连接行为和获取连接信息的方法。比如,远程链接点信息可以获取到,连接的数据冲刷行为可以被控制。这些方法都不是线程安全的。与IBlockingConnection不同的是,INonBlockingConnection在调用read方法直接返回。将IDataHandler对象赋给INonBlockingConnection对象可以使其在新数据到来时被通知。当对应的事件发生时,IDataHandler对象的回调函数会被调用。除了IDataHandler也存在IConnectionHandler对象。服务器端在INonblockingConnection接口上处理接入连接。1、示例:简单TCP服务器首先定义实现了需要的接口(比如,IDataHandler,IConnectHandler,IIdleTimeoutHandler或者IConnectionTimeoutHandler),这个DataHandler会在从连接上接收到数据时被调用。class EchoHandler implements IDataHandler public boolean onData(INonBlockingConnection nbc) throws IOException, BufferUnderflowException, MaxReadSizeExceededException String data = nbc.readStringByDelimiter(rn); nbc.write(data + rn); return true; 然后创建一个服务器实例,并将上面的DataHandler赋给它/ creates the server by passing over the port number & handlerIServer srv = new Server(8090, new EchoHandler(); / run it within the current thread. srv.run(); / the call will not return / . or start it by using a dedicated thread 专用线程srv.start(); / returns after the server has been started与run方法对应的,服务器的start方法创建一个专用的线程来运行服务器。start方法在内部阻塞知道服务器启动,为了确保服务器在执行其他进一步操作前被启动,这是比较好的方法。执行服务器的close方法来优雅的关闭服务器。就像其他面向连接的框架,服务器实现了java.io.Closable接口2、DataHandler的onData方法的语义分析IDataHandler的onData方法会在数据分片被接收后直接调用。要注意的是,在网络层,数据可以被分解成若干个TCP片段也可能被组合打包成一个TCP报文。在客户端执行类似于connection.write(“hello”)的写操作,并不意味着一个TCP报文到达服务器端。xSocket通过内部的读缓冲区缓冲接收到的网络数据来隐藏网络行为。在没有足够数据可用的情况下,数据分片会导致NonBlockingConnection的read方法抛出BufferUnderflowException异常。根据运行模式,在一个挂起的onData方法调用期间没有数据会在网络层被收到。通过使用NONTHREADED模式,xSocket的内部网络I/O线程执行onDataMethod所以不能读取网络层数据。BufferUnderflowException异常不处理是一个惯用的方法,xSocket会在onData方法返回时处理这个异常。class EchoHandler implements IDataHandler / this method will be called each time when data fragments have been received public boolean onData(INonBlockingConnection nbc) throws IOException, ClosedChannelException, BufferUnderflowException, MaxReadSizeExceededException / dont handle the BufferUnderflowException, xSocket will swallow it byte bytes = nbc.readBytesByLength(500); /. return true; 因为没有读到的数据在xSocket的内部缓冲内,onData方法会被再次调用。也就是说,onData方法会在没有新的网络数据包到达时调用,因为xSocket的内部读缓冲区是不空的。这个循环会在内部缓冲区为空或者onData方法读不到数据时结束。xSocket在每次调用onData方法后检查内部读缓冲区是否被修改(新的网络数据到达,或者数据被读出),从而决定是不是要再次调用onData。当连接关闭时,onData方法也会被调用。与处理缓冲区的underflow异常一样,closedChannelException也是不处理的,实现IDisconnectHandler来检测连接关闭。3、写阻塞客户端在客户端,使用IBlockingConnection可以简化套接字处理。与NonBlockingconnection不同的是,BlockingConnection不支持回调处理。IBlockingConnection bc = new BlockingConnection(host, port); String req = Hello server;bc.write(req + rn); / read the whole logical part by waiting (blocking) until / the required data have been receivedString res = bc.readStringByDelimiter(rn); assert (req.equals(res);4、写非阻塞客户端执行阻塞客户端的读方法,调用会在数据接收到或者超时事件发生后返回。为了避免这种情况,客户端需要定义处理Handler,当网络事件发生后被调用。(IDataHandler,IDisconnectHandler)/ defining the client handler (here as a anonymous inner class)IDataHandler clientHandler = new IDataHandler() public boolean onData(INonBlockingConnection nbc) throws IOException, BufferUnderflowException, MaxReadSizeExceededException / read the whole logical part or throwing a BufferUnderflowException String res = nbc.readStringByDelimiter(rn); /. return true; ; / opening the connectionINonBlockingConnection nbc = new NonBlockingConnection(host, port, clientHandler);nbc.write(Hello); / do something else. Receiving data causes that the client / handlers onData method will be called (within a dedicated thread)/.5、使用blocking Connection包装non-blocking ConnectionxSocket在内部使用INonblockingConnection实现IBlockingConnection.。也就是说,BlockingConnection是带有阻塞行为的read方法的包装,于是NonblockingConnection可以随时变成BlockingConnection。INonBlockingConnection nbc = . / wrapping an existing non-blocking connection by a BlockingConnectionIBlockingConnection bc = new BlockingConnection(nbc);bc.readInt();/.6、在服务端包装非阻塞Connection在多数情况下,NonblockingConnection在服务端使用,如果服务器端需要一个BlockingConnection,可以通过包装NonBlockingConnection的方式创建。包装非阻塞Connection会导致赋给其的Handler在内部被移除。典型的是onConnect方法会在服务端创建一个BlockingConnection。.class ConnectHandler implements IConnectHandler public boolean onConnect(INonBlockingConnection nbc) throws IOException IBlockingConnection bc = new BlockingConnection(nbc); / return true; .7、处理连接通过实现IConnectHandler接口,onConnect回调用法会被调用。如果一个新连接简历,这个方法会被调用且仅被调用一次。一般而言,这个方法会被用来对新连接进行安全检查,修改连接属性,准备资源,设置回联或者发送欢迎信息。在这个方法读取数据是不推荐的,因为数据不一定准备好。class Handler implements IDataHandler, IConnectHandler public boolean onConnect(INonBlockingConnection nbc) throws IOException /. e.g. open resources return true; public boolean onData(INonBlockingConnection nbc) throws IOException /. return true; 8、处理连接断开如果Handler实现了IDisconnectHandler接口,onDisconnect会在连接终止的时候调用(不管是当前进程终止连接或者远程终止),尽管连接通过onDisconnect方法被当作参数传递,但是任何读写操作都是不可以进行,因为连接已经不存在。三种关闭的情况:A、客户端主动关闭。这种情况下onDisconnect被直接调用B、连接损坏或者不恰当的关闭,并且被java虚拟机检测到损坏连接。这种情况下,onDisconnect会在检测到损坏连接时调用。C、连接损坏或者不恰当关闭,但是没有被java虚拟机检测到。这种情况下需要实现IIdleTimeoutHandler和IConnectionTimeoutHandler接口,因为onDisconnect不会被调用。class Handler implements IDataHandler, IDisconnectHandler public boolean onDisconnect(INonBlockingConnection nbc) throws IOException /. e.g. closing open resources return true; public boolean onData(INonBlockingConnection nbc) throws IOException ByteBuffer data = connection.readByteBufferByDelimiter(rn); / print out the received data ByteBuffer copy = new ByteBufferdata.length; for (int i = 0; i data.length; i+) copyi = datai.duplicate(); System.out.println(DataConverter.toString(copy); /. return true; 在连接断开的情况下,IDataHandler也被调用(在调用IDisconnectHandler之前)。与本地套接字读取一样,如果连接已经关闭,INonblockingConnection的available方法返回-1。进行读取,会排除ClosedChannelException,如果不处理会被xSocket自动处理。8、异步连接一般的创建阻塞和非阻塞连接都是同步的过程,也就意味着在创建完成后立即可以调用读写方法。不过,一些客户端的非阻塞连接在创建时包含了一个waitForConnect的参数,如果这个参数被设置为false,连接创建者不等待连接完成建立就直接返回。下面展示了如何异步创建连接。同样的,Handler对象需要是想IConnectionExceptionHandler来处理连接异常。class Handler implements IConnectHandler, IDataHandler, IConnectExceptionHandler public boolean onConnect(INonBlockingConnection nbc) throws IOException nbc.write(hello serverrn); /. return true; public boolean onConnectException(INonBlockingConnection nbc, IOException ioe) throws IOException /. return true; public boolean onData(INonBlockingConnection nbc) throws IOException /. return true; Handler hdl = new Handler(); INonBlockingConnection nbc = new NonBlockingConnection(InetAddress.getByName(host), port, hdl, false, 2000); /./ write operations are only valid after the connection has been established which is indicated by the onConect() callback如果在创建非阻塞方法返回后立即调用write方法,由于无法预测连接是否建立完成则会出现竞争条件。onConnect方法的调用标志着连接的完成建立。10、处理超时xSocket支持连接超时和空闲超时。连接超时定义了连接的最长生命周期,与流量无关,连接会在超出连接事件后被关闭。空闲超时定义了在没有数据接收时的最长空闲时间,为了防止没有响应的连接浪费资源,一旦连接空闲时间超时就会被关闭。默认的的超时时间是一个最大值,大概是24天。连接的超时事件可以被用户处理。通过实现IIdleTimeoutHandler和IConnectionTimeoutHandler,对应的onconnectionTimeout和onIdleTimeout方法会被调用。如果这些方法返回true,表明这些事件已经被处理,连接就不会被想Socket关闭。如果返回false,xSocket则会关闭这些连接。连接的空闲超时时间可以针对每一个连接调用setConnectiontimeoutsec()和setIdletimeoutSec()方法设定,同样的也调用这些方法来重设。例如超时在一个超时回调方法中设定并且返回true,那么这个超时事件就会表现的像从来没有发生过。服务端的默认超时行为可以通过服务器端的超时设置函数修改。/ the handlerclass Handler implements IDataHandler, IIdleTimeoutHandler, IConnectionTimeoutHandler public boolean onConnectionTimeout(INonBlockingConnection nbc) throws IOException nbc.write(bye bye); nbc.close(); return true; / prevent, that xSocket also closes the connection public boolean onIdleTimeout(INonBlockingConnection nbc) throws IOException nbc.write(Whats going on? Why dont you send data?); nbc.setIdleTimeoutMillis(30 * 1000); / resets the timeout counter return true; / prevent, that xSocket closes the connection public boolean onData(INonBlockingConnection nbc) throws IOException /. return true; / and the serverIServer server = new Server(8090, new Handler();server.setIdleTimeoutMillis(30 * 1000); / set the default idle timeout for server-side connectionsserver.run();11、回调方法的同步onConnect和onData这样的回调方法会根据连接同步处理,也就是说对伊同一个连接,如果onConnect不执行完成,那么用户也不会调用onData。class Handler implements IConnectHandler, IDataHandler public boolean onConnect(INonBlockingConnection nbc) throws IOException nbc.write(hello serverrn); /. / DO NOT DO THIS! / this causes that onData() will never be called because executing of / callback methods is synchronized based on the connection while (true) try Thread.slepp(1000); catch (InterruptedException ignore) nbc.write(I am alivern); / You could define a TimerTask and run it within a Timer (thread) / to implement the alive issue return true; public boolean onData(INonBlockingConnection nbc) throws IOException String msg = nbc.readStringByDelimiter(rn); /. return true; 12、定义连接作用域的Handler默认的Handler作用域是实例作用域(全局)。也就是同一个Handler可以用于每一个新进入的连接。一个Handler通过实现IConnectionScoped接口来转变成连接作用域的。这个接口需要一个可以被用来为新连接创建专门Handler实例的clone方法。为了避免副作用,clone方法需要实现成深度拷贝。class SmtpHandler implements IDataHandler, IConnectionScoped private int handledMessages = 0; private SessionData sessionData = new SessionData(); public boolean onData(INonBlockingConnection nbc) throws IOException /. return true; / deep clone: all attributes beside primitives, immutable or / global manager/service references have also to be cloned public Object clone() throws CloneNotSupportedException SmtpHandler copy = (SmtpHandler) super.clone(); copy.sessionData = (SessionData) this.sessionData.clone(); return copy; 通过声明Handler为连接作用域,在支持深度拷贝的情况下,Handler的变量自动变成连接指定的。同时除了这种显式的往连接发送数据的方法之外,隐式的方法也是支持的。13、绑定会话相关的数据到连接一个可选的向连接分发会话数据的方法是直接附加数据。一般而言,这是推荐的方法。一个连接支持附件特定连接的会话数据通过setAttachment(object),getAttachment()方法。class SmtpHandler implements IConnectHandler, IDataHandler public boolean onConnect(INonBlockingConnection nbc) throws IOException nbc.setAttachment(new SessionData(); return true; public boolean onData(INonBlockingConnection nbc) throws IOException SessionData sessionData = (SessionData) nbc.getAttachment(); /. return true; 14、运行时替换HandlerxSocket支持在运行时替换Handler,这可以在服务器端为所有新进入的连接应用新的Handler。如果连接已经建立,可以调用setHandler方法来替换当前连接的Handler。class ServerHandlerA implements IDataHandler public boolean onData(INonBlockingConnection nbc) throws IOException String cmd = nbc.readStringByDelimiter(rn); if (cmd.equals(switch) nbc.setHandler(new ServerHandlerB(); else nbc.write(A + cmd + rn); return true; 在服务器端Handler赋给了server,这个Handler会赋值给每一个新进入的连接,可以通过调用setHandler方法来替换。class ServerSideHandler implements IDataHandler Resource private Server server; public boolean onData(INonBlockingConnection connection) throws IOException String cmd = connection.readStringByDelimiter(rn); if (cmd.equals(switch) server.setHandler(new ServerHandlerB(); connection.write(switchedrn); connection.write(switchedrn); else connection.write(A + cmd + rn); return true; 15、示例:简单的基于长度的Handler为了应用基于长度的通信方法,连接的mark-support可以使用,这种情况下,客户端首先写一个空的长度属性,在写完内容数据之后,写指针会移回到长度属性域来覆盖长度属性域。IBlockingConnection bc = new BlockingConnection(host, port);bc.setAutoflush(false); / mark support requires deactivated autoflush! bc.markWritePosition(); / mark current positionbc.write(int) 0); / write emtpy length field int written = bc.write(hello world);written += bc.write( its nice to be here);/.bc.resetToWriteMark(); / return to length field positionbc.write(written); / and update it bc.flush(); / flush (marker will be removed implicit)16、服务器端public boolean onData(INonBlockingConnection nbc) throws IOException, BufferUnderflowException / validate that enough data is available (if / not an BufferUnderflowException will be thrown) int length = ConnectionUtils.validateSufficientDatasizeByIntLengthField(nbc) String text = nbc.readStringByLength(length); nbc.write(text); return true;17、更复杂的例子:多部分数据一般而言,一个数据记录包含有多个部分。比如一个数据记录以头字段开始,然后接着是数据内容,典型的头包含有一个长度字段。IBlockingConnection bc = new BlockingConnection(host, port);bc.setAutoflush(false);bc.write(RECORD_TYPE_A); / record typebc.write(int) 2); / versionbc.write(sign); / signaturebc.write(length); / data lengthbc.flush();bc.write(data); / databc.flush(); String status = bc.readStringByDelimiter(rn);/.18、服务器端(事务性读、动态Handler替换)就像上面讨论的一样,数据在网络层被分片。当onData方法被调用时,并不预示着有多少字节被接收。通过调用读方法(readInt、readStringByDelimiter,会产生一个BufferUnderflowException异常。为了处理这个异常,可以使用读标记。class ProtocolHandler implements IDataHandler public boolean onData(INonBlockingConnection con
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 商务局成立健康工作制度
- 四年级质量监测工作制度
- 国企污水处理厂工作制度
- 4.1.1 n次方根与分数指数幂(第一课时)学案-高中数学人教A版(2019)必修第一册
- 地市车辆管理所工作制度
- 未来五年经药物浸涂胶粘敷料市场需求变化趋势与商业创新机遇分析研究报告
- 垃圾分类日常维保工作制度
- 基层派出所防火工作制度
- 处置子平台相关工作制度
- 2025年三防工作制度
- 2025年武汉建筑类高级职称评审水平能力测试有效题库
- 2025成都辅警笔试题库及答案
- 数字计量:引领未来-探究数字化计量服务的崛起与挑战
- 浆砌片石施工技术标准说明
- 慢性支气管炎课件
- LNG液化天然气卸车标准作业流程
- 索尼微单相机A7 II(ILCE-7M2)使用说明书
- 三体系认证培训课件
- 2026年高考英语-2024年新课标II卷词汇清单
- 做自强不息的中国人+说课课件2024-2025学年统编版道德与法治七年级下册
- T/CECS 10235-2022绿色建材评价人造石
评论
0/150
提交评论