Nio多线程CS收发信息问题(问题已经解决)
刚开始研究Java的NIO,就碰上了个问题,现在服务器端和客户段一个发一个收没有问题,但要是客户端和服务器段同时发收就有问题(我说的是双向的意思),这是为什么呢?相不明白,大家帮看看。服务器端代码:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */package niocs.newpackage.service;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.util.Iterator;import javax.swing.JTextPane;import niocs.NIOCSView;import niocs.newpackage.service.If.IServerConnect;/** * * @author Administrator */public class SetUpServer implements Runnable,IServerConnect{ private final static int MAXACCEPT = 2048; private NIOCSView serverShow; private ByteBuffer w_Buff = ByteBuffer.allocate(MAXACCEPT); private final static String ENTER = "\r\n"; private int port; private JTextPane messageContent; private StringBuilder message = new StringBuilder(); private String fMessage = null; public SetUpServer(NIOCSView server) { this.serverShow = server; setUPServer(); } private void setUPServer() { try { messageContent = this.serverShow.getContent(); message.append("正在初始化端口"); message.append(ENTER); messageContent.setText(message.toString()); port = Integer.parseInt(this.serverShow.getPort().getModel().getValue().toString()); message.append("初始化端口成功!"); message.append(ENTER); messageContent.setText(message.toString()); } catch(ClassCastException e) { port = 0; message.append("端口初始化失败!"); message.append(ENTER); messageContent.setText(message.toString()); } } public void run() { try { ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); Selector s = Selector.open(); ssc.socket().bind(new InetSocketAddress(port)); showMessage("系统正在建立对" + port + "端口的监听"); ssc.register(s,SelectionKey.OP_ACCEPT); showMessage("系统已经启动!"); while(true) { int n = s.select(); if(n == 0) { continue; } Iterator it = s.selectedKeys().iterator(); while(it.hasNext()) { SelectionKey key = (SelectionKey) it.next(); it.remove(); if(key.isAcceptable()) { showMessage("有人连接到服务器."); ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel sc = server.accept(); showMessage("接受此连接请求"); sc.configureBlocking(false); sc.register(s, SelectionKey.OP_READ); } if(key.isReadable()) { SocketChannel sc = (SocketChannel)key.channel(); showMessage("正在读取数据"); if(!readData(sc)) { key.cancel(); break; } sc.configureBlocking(false); sc.register(s, SelectionKey.OP_WRITE); } if(key.isWritable()) { SocketChannel sc = (SocketChannel)key.channel(); showMessage("向客户端发送数据"); fMessage = "123456"; if(!writeData(sc, fMessage)) { key.cancel(); break; } sc.configureBlocking(false); sc.register(s, SelectionKey.OP_READ); } } } } catch(IOException e) { e.printStackTrace(); showMessage("读取时出错"); return; } } private void showMessage(String aMessage) { message.append(aMessage); message.append(ENTER); messageContent.setText(message.toString()); } private boolean readData(SocketChannel sc) throws IOException { ByteBuffer r_Buff = ByteBuffer.allocate(MAXACCEPT); try { r_Buff.clear(); while(sc.read(r_Buff) > 0) { r_Buff.flip(); fMessage = new String(r_Buff.array()).trim(); showMessage("收的数据是:" + fMessage); } r_Buff = null; return true; } catch(IOException e) { System.err.println("又报错了"); r_Buff.clear(); r_Buff.clear(); return false; } catch(NullPointerException e) { System.err.println("丫的出来空指针了"); return false; } } private boolean writeData(SocketChannel sc,String message) { try { w_Buff.clear(); w_Buff.put(message.getBytes()); w_Buff.flip(); while(w_Buff.hasRemaining()) sc.write(w_Buff); w_Buff.clear(); return true; } catch(IOException e) { System.err.println("sever已"); return false; } catch(NullPointerException e) { System.err.println("过去了都."); return false; } } public int getConnectPort() { return port; }}
这段代码实现了,接收和发送,即:服务器段受到什么就再返还给客户端。
客户端:线程1读线程
/* * To change this template, choose Tools | Templates * and open the template in the editor. */package nioclien.backClass;import java.io.IOException;import java.net.ConnectException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.Set;import javax.swing.JTextArea;import nioclien.JSendMessage;/** * * @author Administrator */public class ClienReadServer implements Runnable{ private final static int MAXSIZE = 2048; private final static String ENTER = "\r\n"; private ByteBuffer w_Buff = ByteBuffer.allocate(MAXSIZE); private static String host; private int port; private JSendMessage sender; private StringBuilder message = new StringBuilder(); private JTextArea messageReciver; public ClienReadServer(JSendMessage sender) { this.sender = sender; messageReciver = sender.getReceiveText(); initForm(); } private void initForm() { try { port = Integer.parseInt(this.sender.getPort().getText()); host = this.sender.getIPText().getText(); } catch(NumberFormatException e) { port = 0; message.append("初始化端口失败"); message.append(ENTER); messageReciver.setText(message.toString()); } } @SuppressWarnings({"static-access", "empty-statement"}) public void run() { if(host.trim().startsWith(".")) { this.sender.getConnectMenuItem().setEnabled(true); return; } try { SocketChannel channel = SocketChannel.open(new InetSocketAddress(host, port)); channel.configureBlocking(false); Selector selector = Selector.open(); SelectionKey skey = channel.register(selector, SelectionKey.OP_READ); showMessage("与" + host + "已经成功连接,您现在可以发送消息了."); boolean stop = false; int n = 0; int read = 0; while(!stop) { n = selector.select(); if(n > 0) { Set set = selector.selectedKeys(); Iterator it = set.iterator(); while(it.hasNext()) { skey = (SelectionKey) it.next(); it.remove(); if(skey.isReadable()) { SocketChannel sc = (SocketChannel) skey.channel(); readServer(sc); } } } } } catch(ConnectException e) { this.sender.getConnectMenuItem().setEnabled(true); System.err.println("连接服务器失败."); return; } catch(IOException e) { e.printStackTrace(); } } @SuppressWarnings("empty-statement") public void readServer(SocketChannel sc) throws IOException { try { ByteBuffer r_Buff = ByteBuffer.allocate(MAXSIZE); r_Buff.clear(); while(sc.read(r_Buff) > 0) { r_Buff.flip(); showMessage("收的数据是:" + new String(r_Buff.array()).trim()); } } catch(NullPointerException e) { System.err.println("时间上的问题."); } } private void showMessage(String aMessage) { message.append(aMessage); message.append(ENTER); messageReciver.setText(message.toString()); } }
客户端线程2:写线程,向服务器端发送信息。
/* * To change this template, choose Tools | Templates * and open the template in the editor. */package nioclien.backClass;import java.io.IOException;import java.net.ConnectException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;import java.util.LinkedList;import javax.swing.JTextArea;import nioclien.JSendMessage;/** * * @author Administrator */public class ClienServer implements Runnable{ private SocketChannel sc; private final static int MAXSIZE = 2048; private final static String ENTER = "\r\n"; private ByteBuffer w_Buff = ByteBuffer.allocate(MAXSIZE); private static String host; private int port; private JSendMessage sender; private StringBuilder message = new StringBuilder(); private FQueue<String> fQueue = new FQueue<String>(); public ClienServer(JSendMessage sender) { this.sender = sender; initForm(); } private void initForm() { try { port = Integer.parseInt(this.sender.getPort().getText()); host = this.sender.getIPText().getText(); } catch(NumberFormatException e) { port = 0; message.append("初始化端口失败"); message.append(ENTER); } } @SuppressWarnings({"static-access", "empty-statement"}) public void run() { if(host.trim().startsWith(".")) { return; } try { InetSocketAddress addr = new InetSocketAddress(host, port); sc = SocketChannel.open(); sc.connect(addr); while(!sc.finishConnect());//等待建立连接 while(true) { try { synchronized(fQueue) { if(!fQueue.isEmpty()) { String temp = fQueue.get(); System.out.println("要发送的数据是:" + temp); w_Buff.clear(); w_Buff.put(temp.getBytes()); w_Buff.flip(); while(w_Buff.hasRemaining()) sc.write(w_Buff); w_Buff.clear(); } } } catch(Exception e) { System.err.print("丫的没发送成功"); } Thread.currentThread().sleep(1000); } } catch(ConnectException e) { this.sender.getConnectMenuItem().setEnabled(true); System.err.println("连接服务器失败."); return; } catch(IOException e) { e.printStackTrace(); } catch(InterruptedException e) { e.printStackTrace(); } } public void sendMessage(String aMessage) { fQueue.put(aMessage); } private class FQueue<T> { private LinkedList<T> flist = new LinkedList<T>(); public void put(T o) { flist.addLast(o); } public T get() { return flist.removeFirst(); } public boolean isEmpty() { return flist.isEmpty(); } }}
不知道为什么当写线程向服务器发出信息后,服务器又返还信息,客户端读线程好象并没有接收到。这是为什么呢?
页:
[1]