techno_it 发表于 2013-1-29 23:31:49

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]
查看完整版本: Nio多线程CS收发信息问题(问题已经解决)