Java nio 实现socket异步通信 (对Java nio 实习笔记五中内容做一纠正)

来源:互联网 发布:医院网络割接方案 编辑:程序博客网 时间:2024/06/01 09:19

原始错误版本请看:http://blog.csdn.net/tsyj810883979/article/details/6877216

在原有基础上考虑了编码与解码的问题,还有消息发送的两个重要方法调用疏忽

public abstract int write(ByteBuffer src)     将字节序列从给定的缓冲区中写入此通道。 
public abstract int read(ByteBuffer dst)     将字节序列从此通道中读入给定的缓冲区。

下面代码在关闭连接时还有问题,服务器可以与客户端断开,但是客户端断开后没有退出,再次操作会出现异常。

 

服务器端代码实现:

import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Calendar;import java.util.Iterator;public class TestServer {public static void main(String[] args) {new Thread(new EchoServer(1982)).start();}}class EchoServer implements Runnable {//要监听的端口号private int port;//生成一个信号监视器private Selector s;//读缓冲区private ByteBuffer r_bBuf = ByteBuffer.allocate(1024);private ByteBuffer w_bBuf;public EchoServer(int port) {this.port = port;try {s = Selector.open();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() {try {//生成一个ServerScoket通道的实例对象,用于侦听可能发生的IO事件ServerSocketChannel ssc = ServerSocketChannel.open();//将该通道设置为异步方式ssc.configureBlocking(false);//绑定到一个指定的端口ssc.socket().bind(new InetSocketAddress(port));//注册特定类型的事件到信号监视器上ssc.register(s, SelectionKey.OP_ACCEPT);System.out.println("The server has been launched...");while(true) {//将会阻塞执行,直到有事件发生s.select();Iterator<SelectionKey> it = s.selectedKeys().iterator();while(it.hasNext()) {SelectionKey key = it.next();//key定义了四种不同形式的操作switch(key.readyOps()) {case SelectionKey.OP_ACCEPT :dealwithAccept(key);break;case SelectionKey.OP_CONNECT :break;case SelectionKey.OP_READ :dealwithRead(key);break;case SelectionKey.OP_WRITE :break;}//处理结束后移除当前事件,以免重复处理it.remove();}}} catch (IOException e) {e.printStackTrace();}}//处理接收连接的事件private void dealwithAccept(SelectionKey key) {try {System.out.println("新的客户端请求连接...");ServerSocketChannel server = (ServerSocketChannel)key.channel();SocketChannel sc = server.accept();sc.configureBlocking(false);//注册读事件sc.register(s, SelectionKey.OP_READ);System.out.println("客户端连接成功...");} catch (IOException e) {e.printStackTrace();}}//处理客户端发来的消息,处理读事件private void dealwithRead(SelectionKey key) {try {SocketChannel sc = (SocketChannel)key.channel();System.out.println("读入数据");r_bBuf.clear();//将字节序列从此通道中读入给定的缓冲区r_bBufsc.read(r_bBuf);r_bBuf.flip();String msg = Charset.forName("UTF-8").decode(r_bBuf).toString();if(msg.equalsIgnoreCase("time")) {w_bBuf = ByteBuffer.wrap(getCurrentTime().getBytes("UTF-8"));sc.write(w_bBuf);w_bBuf.clear();} else if(msg.equalsIgnoreCase("bye")) {sc.write(ByteBuffer.wrap("已经与服务器断开连接".getBytes("UTF-8")));sc.socket().close();} else {sc.write(ByteBuffer.wrap(msg.getBytes("UTF-8")));}System.out.println(msg);System.out.println("处理完毕...");r_bBuf.clear();try {Thread.currentThread();Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}} catch (IOException e) {e.printStackTrace();}}private String getCurrentTime() {Calendar date = Calendar.getInstance();String time = "服务器当前时间:" +  date.get(Calendar.YEAR) + "-" +  date.get(Calendar.MONTH)+1 + "-" +  date.get(Calendar.DATE) + " " +  date.get(Calendar.HOUR) + ":" +  date.get(Calendar.MINUTE) + ":" +  date.get(Calendar.SECOND);return time;}}

 

客户端代码实现:

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;public class TestClient {public static void main(String[] args) {new MiniClient("localhost", 1982);}}class MiniClient {private SocketChannel sc;private ByteBuffer w_bBuf;private ByteBuffer r_bBuf = ByteBuffer.allocate(1024);public MiniClient(String host, int port) {try {InetSocketAddress remote = new InetSocketAddress(host, port);sc = SocketChannel.open();sc.connect(remote);if(sc.finishConnect()) {System.out.println("已经与服务器成功建立连接...");}while(true) {if(!sc.socket().isConnected()) {System.out.println("已经与服务器失去了连接...");return ;}BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String str = br.readLine();System.out.println("读入一行数据,开始发送...");w_bBuf = ByteBuffer.wrap(str.getBytes("UTF-8"));//将缓冲区中数据写入通道sc.write(w_bBuf);System.out.println("数据发送成功...");w_bBuf.clear();System.out.println("接收服务器端响应消息...");try {Thread.currentThread();Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}r_bBuf.clear();//将字节序列从此通道中读入给定的缓冲区r_bBufsc.read(r_bBuf);r_bBuf.flip();String msg = Charset.forName("UTF-8").decode(r_bBuf).toString();System.out.println(msg);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
原创粉丝点击