日期:2014-05-20 浏览次数:20721 次
package nio; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; 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.text.DateFormat; import
------解决方案--------------------
一下子看不出来,你试试我这个Client,我本地是可以用的:
package nio; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class EchoTestClient { private static int SOCKET_NUM = 55555; private static DateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd HH:mm:ss"); /** * @param args */ public static void main(String[] args) { new EchoTestClient().start(); } private void start() { SocketChannel client = null; try { Selector selector = Selector.open(); // 定义一个记录套接字通道事件的对象 client = connect(selector); String a = "ABCD你好1234"; // 要发送的数据 while (true) { ByteBuffer sendbuffer = ByteBuffer.allocate(40); // 定义用来存储发送数据的byte缓冲区 ByteBuffer readBuffer = ByteBuffer.allocate(40); // 定义用于接收服务器返回的数据的缓冲区 sendbuffer.put(a.getBytes()); // 将数据put进缓冲区 sendbuffer.flip(); // 将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位 client.write(sendbuffer); // 向服务器发送数据 log("Send to server: " + new String(sendbuffer.array())); // 利用循环来读取服务器发回的数据 { // 如果客户端连接没有打开就退出循环 if (!client.isOpen()) break; // 此方法为查询是否有事件发生如果没有就阻塞,有的话返回事件数量 int shijian = selector.select(1000); // 如果没有事件返回循环 if (shijian == 0) { continue; } // 定义一个临时的客户端socket对象 SocketChannel sc; // 遍例所有的事件 for (SelectionKey key : selector.selectedKeys()) { // 删除本次事件 selector.selectedKeys().remove(key); // 如果本事件的类型为read时,表示服务器向本客户端发送了数据 if (key.isReadable()) { // 将临时客户端对象实例为本事件的socket对象 sc = (SocketChannel) key.channel(); // 定义一个用于存储所有服务器发送过来的数据 ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 将缓冲区清空以备下次读取 readBuffer.clear(); // 此循环从本事件的客户端对象读取服务器发送来的数据到缓冲区中 while (sc.read(readBuffer) > 0) { // 将本次读取的数据存到byte流中 bos.write(readBuffer.array()); // 将缓冲区清空以备下次读取 readBuffer.clear(); } // 如果byte流中存有数据 if (bos.size() > 0) { // 建立一个普通字节数组存取缓冲区的数据 byte[] b = bos.toByteArray(); log("Recive from server: " + new String(b)); } } } } Thread.sleep(2000); } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭客户端连接,此时服务器在read读取客户端信息的时候会返回-1 if (client != null) { try { client.close(); } catch (IOException e) { } log("Connection closed!"); } } } private SocketChannel connect(Selector selector) throws IOException { SocketAddress address = new InetSocketAddress("localhost", SOCKET_NUM); // 定义一个服务器地址的对象 SocketChannel client = SocketChannel.open(address); // 定义异步客户端 client.configureBlocking(false); // 将客户端设定为异步 client.register(selector, SelectionKey.OP_READ); // 在轮讯对象中注册此客户端的读取事件(就是当服务器向此客户端发送数据的时候) return client; } private static void log(Object msg) { System.out.println("CLIENT [" + dateFormatter.format(new Date()) + "]: " + msg); } }