android socketchannel的使用源代码_第1页
android socketchannel的使用源代码_第2页
android socketchannel的使用源代码_第3页
android socketchannel的使用源代码_第4页
android socketchannel的使用源代码_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

使用 SocketChannel 的 NIO 客户机服务器通信示例。(转) 这只是长征路上的一小步,以后还有待改进。 NIO Selector 示意图: 客户端代码: import java.io.IOException; import .InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; /* * NIO TCP 客户端 * * date 2010-2-3 * time 下午 03:33:26 * version 1.00 */ public class TCPClient / 信道选择器 private Selector selector; / 与服务器通信的信道 SocketChannel socketChannel; / 要连接的服务器 Ip 地址 private String hostIp; / 要连接的远程服务器在监听的端口 private int hostListenningPort; /* * 构造函数 * param HostIp * param HostListenningPort * throws IOException */ public TCPClient(String HostIp,int HostListenningPort)throws IOException this.hostIp=HostIp; this.hostListenningPort=HostListenningPort; initialize(); /* * 初始化 * throws IOException */ private void initialize() throws IOException / 打开监听信道并设置为非阻塞模式 socketChannel=SocketChannel.open(new InetSocketAddress(hostIp, hostListenningPort); socketChannel.configureBlocking(false); / 打开并注册选择器到信道 selector = Selector.open(); socketChannel.register(selector, SelectionKey.OP_READ); / 启动读取线程 new TCPClientReadThread(selector); /* * 发送字符串到服务器 * param message * throws IOException */ public void sendMsg(String message) throws IOException ByteBuffer writeBuffer=ByteBuffer.wrap(message.getBytes(“UTF-16“); socketChannel.write(writeBuffer); public static void main(String args) throws IOException TCPClient client=new TCPClient(““,1978); client.sendMsg(“你好!Nio!醉里挑灯看剑,梦回吹角连营“); 客户端读取线程代码: import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; public class TCPClientReadThread implements Runnable private Selector selector; public TCPClientReadThread(Selector selector) this.selector=selector; new Thread(this).start(); public void run() try while (selector.select() 0) / 遍历每个有可用 IO 操作 Channel 对应的 SelectionKey for (SelectionKey sk : selector.selectedKeys() / 如果该 SelectionKey 对应的 Channel 中有可读的数据 if (sk.isReadable() / 使用 NIO 读取 Channel 中的数据 SocketChannel sc = (SocketChannel) sk.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); sc.read(buffer); buffer.flip(); / 将字节转化为为 UTF-16 的字符串 String receivedString=Charset.forName(“UTF-16“).newDecoder().decode(buffer).toString(); / 控制台打印出来 System.out.println(“接收到来自服务器 “+sc.socket().getRemoteSocketAddress()+“的信息: “+receivedString); / 为下一次读取作准备 erestOps(SelectionKey.OP_READ); / 删除正在处理的 SelectionKey selector.selectedKeys().remove(sk); catch (IOException ex) ex.printStackTrace(); 服务器端代码: import java.io.IOException; import .InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.util.Iterator; /* * TCP 服务器端 * * date 2010-2-3 * time 上午 08:39:48 * version 1.00 */ public class TCPServer / 缓冲区大小 private static final int BufferSize=1024; / 超时时间,单位毫秒 private static final int TimeOut=3000; / 本地监听端口 private static final int ListenPort=1978; public static void main(String args) throws IOException / 创建选择器 Selector selector=Selector.open(); / 打开监听信道 ServerSocketChannel listenerChannel=ServerSocketChannel.open(); / 与本地端口绑定 listenerChannel.socket().bind(new InetSocketAddress(ListenPort); / 设置为非阻塞模式 listenerChannel.configureBlocking(false); / 将选择器绑定到监听信道 ,只有非阻塞信道才可以注册选择器.并在注册过程中指出该信道可以进行 Accept 操作 listenerChannel.register(selector, SelectionKey.OP_ACCEPT); / 创建一个处理协议的实现类 ,由它来具体操作 TCPProtocol protocol=new TCPProtocolImpl(BufferSize); / 反复循环,等待 IO while(true) / 等待某信道就绪(或超时) if(selector.select(TimeOut)=0) System.out.print(“独自等待.“); continue; / 取得迭代器.selectedKeys()中包含了每个准备好某一 I/O 操作的信道的 SelectionKey Iterator keyIter=selector.selectedKeys().iterator(); while(keyIter.hasNext() SelectionKey key=keyIter.next(); try if(key.isAcceptable() / 有客户端连接请求时 protocol.handleAccept(key); if(key.isReadable() / 从客户端读取数据 protocol.handleRead(key); if(key.isValid() catch(IOException ex) / 出现 IO 异常(如客户端断开连接)时移除处理过的键 keyIter.remove(); continue; / 移除处理过的键 keyIter.remove(); 协议接口代码: import java.io.IOException; import java.nio.channels.SelectionKey; /* * TCPServerSelector 与特定协议间通信的接口 * * date 2010-2-3 * time 上午 08:42:42 * version 1.00 */ public interface TCPProtocol /* * 接收一个 SocketChannel 的处理 * param key * throws IOException */ void handleAccept(SelectionKey key) throws IOException; /* * 从一个 SocketChannel 读取信息的处理 * param key * throws IOException */ void handleRead(SelectionKey key) throws IOException; /* * 向一个 SocketChannel 写入信息的处理 * param key * throws IOException */ void handleWrite(SelectionKey key) throws IOException; 协议实现类代码: import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Date; /* * TCPProtocol 的实现类 * * date 2010-2-3 * time 上午 08:58:59 * version 1.00 */ public class TCPProtocolImpl implements TCPProtocol private int bufferSize; public TCPProtocolImpl(int bufferSize) this.bufferSize=bufferSize; public void handleAccept(SelectionKey key) throws IOException SocketChannel clientChannel=(ServerSocketChannel)key.channel().accept(); clientChannel.configureBlocking(false); clientChannel.register(key.selector(), SelectionKey.OP_READ,ByteBuffer.allocate(bufferSize); public void handleRead(SelectionKey key) throws IOException / 获得与客户端通信的信道 SocketChannel clientChannel=(SocketChannel)key.channel(); / 得到并清空缓冲区 ByteBuffer buffer=(ByteBuffer)key.attachment(); buffer.clear(); / 读取信息获得读取的字节数 long bytesRead=clientChannel.read(buffer); if(bytesRead=-1) / 没有读取到内容的情况 clientChannel.close(); else / 将缓冲区准备为数据传出状态 buffer.flip(); / 将字节转化为为 UTF-16 的字符串 String receivedString=Charset.forName(“UTF-16“).newDecoder().decode(buffer).toString(); / 控制台打印出来 System.out.println(“接收到来自 “+clientChannel.socket().getRemoteSocketAddress()+“的信息: “+receivedString); / 准备发送的文本 String sendString=“你好, 客户端 . “+new Date().toString()+“,已经收到你的信息“+receivedString; buffer=ByteBuffer.wrap(sendString.getBytes(“UTF-16“); clientChannel.write(buffer); / 设置为下一次读取或是写入做准备 erestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); public void handleWrite(SelectionKey key) throws IOException / do nothing SocketChannel 使用心得 博客分类: Java 的基础知识 1,服务器端,而(真)一直等待客户端来连接。 基本步骤为: Java 的代码 1. ServerSocketChannel 实例服务器 = ServerSocketChannel.open(); 2. server.configureBlocking(假 ); 3. 4. server.socket()。结合(新 InetSocketAddress 的(5200 ); 5. 6. 选择选择= Selector.open(); 7. server.register(选择,SelectionKey.OP_ACCEPT); 声明一个等待客户端的服务器。 Java 的代码 1. select.select(); 2. 设置 readkeys = select.selectedKeys(); 3. 迭代器迭代器 readkeys.iterator(); 4. ,而 (iterator.hasNext () 5. SelectionKey 的关键=(SelectionKey 的)iterator.next(); 6. 如果 (key.isAcceptable 的() 7. 的 SocketChannel 实例的客户端= (ServerSocketChannel 实例)key.channel()(); 8. (“接受连接:” +客户端); 9. client.configureBlocking(假); 10. client.register(key.selector (),SelectionKey.OP_READ ByteBuffer.allocate(10 24 ); 11. 12. 如果 (key.isReadable() 13. 14. / /获得与客户端通信的信道 15. 的 SocketChannel clientChannel =(的 SocketChannel)key.channel(); 16. 17. / /得到并清空缓冲区 18. ByteBuffer 的缓冲=(ByteBuffer 的)key.attachment (); 19. buffer.clear(); 20. 21. / /读取信息获得读取的字节数 22. 长 bytesRead clientChannel.read(缓冲区); 23. 24. (bytesRead = - 1 ) 25. / /没有读取到内容的情况 26. clientChannel.close(); 27. 其他 28. / /将缓冲区准备为数据传出状态 29. buffer.flip(); 30. 31. / /将字节转化为为 UTF-16 的字符串 32. (“UTF-16” ) receivedString = Charset.forName 。newDecoder ()。解码(缓冲 区)。toString()方法; 33. 34. / /控制台打印出来 35. (“接收设为来自 ” + clientChannel.socket()。 getRemoteSocketAddress()+ “的 信息:” + receivedString); 36. 37. / /准备发送的文本 38. 字符串 SendString 中= “你好,客户端。” + 新的 日期()。的 toString()+ “ ,已经收到你的信息” + receivedString; 39. 缓冲 ByteBuffer.wrap(sendString.getBytes(“UTF-16” ); 40. clientChannel.write(缓冲液); 41. 42. / /设置为下一次读取或是写入做准备 43. erestOps(SelectionKey.OP_READ SelectionKey.OP_WRITE); 44. 45. 46. 如果 (key.isWritable() 47. 48. 的 SocketChannel SC =(的 SocketChannel)key.channel(); 49. ByteBuffer 的 writeBuffer ByteBuffer.wrap( “ 我的程序员之道” 。GetBytes 会(“UTF- 16” ); 50. sc.write(writeBuffer); 51. 52. key.channel()() ; 53. 遍历键集,然后判断键的可读可写等做不同的操作 客户端建立一个线程,等待服务器端的回应: 1.建立基本的 SocketChannel Java 的代码 1. 的 SocketChannel SC = SocketChannel.open(新 InetSocketAddress 的(“1” , 5200 ); 2. / /打开一个 SocketChannel 实例并连接到服务器 3. sc.configureBlocking(假); 4. 5. 选择器= Selector.open(); 6. 7. sc.register(选择,SelectionKey.OP_READ); 在实现可运行的运行方法扩展功能里遍历键集,判断做不同的操作: Java 的代码 1. 而 (selector.select() 0 ) 2. / /遍历每个有可用 IO 操作通道对应的 SelectionKey 的 3. 迭代器 selector.selectedKeys()的 iterator(); 4. 而 (it.hasNext () 5. SelectionKey 的 SK =(的 Selec

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论