`
techno_it
  • 浏览: 54520 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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();
        }
    }

}

不知道为什么当写线程向服务器发出信息后,服务器又返还信息,客户端读线程好象并没有接收到。这是为什么呢?
  • 描述: 效果页面
  • 大小: 77.2 KB
分享到:
评论
2 楼 alexlee002 2009-11-13  
那是怎么解决的呢?
1 楼 yzhong_sa 2009-02-18  
服务器端有没有执行数据的发送操作???

相关推荐

    基于事件的 NIO 多线程服务器

    基于事件的 NIO 多线程服务器

    基于事件的_NIO_多线程服务器

    ### 基于事件的NIO多线程服务器解析 #### 概述 在Java的网络编程中,NIO(Non-blocking I/O)作为一种高效的数据处理模式,自JDK 1.4版本引入以来,逐渐成为了开发高性能网络应用的重要工具之一。与传统的阻塞I/O...

    使用多线程的NIO构建简易的多线程java服务器

    在Java编程中,使用非阻塞I/O(Non-blocking Input/Output,NIO)和多线程技术可以构建高效、可扩展的服务器。本篇我们将深入探讨如何利用NIO和多线程来创建一个简单的Java服务器。首先,我们需要理解NIO的基本概念...

    NIO-实践-多线程实例

    NIO用于高性能Socket编程由来已久,网络也有较为丰富的原理和源代码。我这里主要介绍几点经验总结: ...本文粘贴多线程在NIO环境下的基本运用示例代码,同时演示了一个线程如何对多个连接进行读写的操作。

    基于时间的NIO多线程服务器

    ### 基于时间的NIO多...该模型不仅解决了传统多线程服务器存在的线程开销问题,还通过合理的事件机制实现了系统的可扩展性和可维护性。对于开发者来说,理解并运用这一模型可以在服务器端开发中获得更好的性能表现。

    java多线程nio服务器

    Java NIO服务器的多线程设计有助于提高服务器的并发性能,特别是在高并发场景下,可以有效地利用系统资源,避免大量线程导致的内存消耗和上下文切换开销。同时,通过选择器的使用,减少了对主线程的占用,使得服务器...

    基于事件的NIO多线程服务器打包

    该包封装过的NIO比sun本身的更容易处理 server中只有区区几行就搞定了: //创建listener TimeHandler timer = new TimeHandler(); //获取Notifier Notifier notifier = Notifier.getNotifier(); //注册监听 notifier....

    基于事件的NIO多线程服务器

    【事件回调机制】在基于事件的NIO多线程服务器设计中,事件回调机制是核心组件之一。事件回调允许服务器在特定事件发生时调用预定义的处理函数,以执行相应的业务逻辑。这种方式使得代码更加模块化,易于扩展和维护...

    Java Socket学习---nio实现阻塞多线程通信

    本篇文章将深入探讨如何使用Java NIO(非阻塞I/O)来实现阻塞多线程通信,这对于高性能服务器端应用尤其重要。我们将会分析`EchoServer.java`、`EchoClient.java`和`SocketUtils.java`这三个文件中的关键知识点。 ...

    基于HTTP、NIO、多线程实现浏览器高并发非阻塞访问服务器文件

    代码经过压力测试,采用反应器模式,没有第三方框架,实现功能:可以一个线程处理多个请求,也可以加上多线程。处理数据采用的多线程。实现功能:基于HTTP协议,解析请求和拼接响应,基于NIO的非阻塞,线程池,文件...

    NIO_RandomAccessFile_多线程_按行读本地CSV文件(java==> google guava包ListenableFuture)

    NIO_RandomAccessFile_多线程读本地CSV文件(java==&gt; google guava包ListenableFuture) reader里有个main函数,更改文件路径后,直接运行即可

    基于NIO的多线程聊天系统

    基于NIO的多线程聊天系统,代码很少,很经典,51CTO网站上的代码。有登陆和聊天界面。代码结构层次清晰,系统只有6个类。

    多线程精品资源--Java NIO+多线程实现聊天室.zip

    在这个“多线程精品资源--Java NIO+多线程实现聊天室”的压缩包中,我们可以推测它包含了一套关于如何使用Java NIO和多线程技术来创建一个实时聊天应用的教程或示例代码。 首先,多线程是Java中并行处理的基础。...

    java多线程读取文件

    Java多线程读大文件 java多线程写文件:多线程往队列中写入数据

    java多线程程序设计:Java NIO+多线程实现聊天室

    java多线程程序设计:Java NIO+多线程实现聊天室 Java基于多线程和NIO实现聊天室 涉及到的技术点 线程池ThreadPoolExecutor 阻塞队列BlockingQueue,生产者消费者模式 Selector Channel ByteBuffer ProtoStuff 高...

    java NIO socket聊天室

    使用NIO socket不需要多线程来处理多个连接的请求,效率非常高 可以作为NIO socket入门的例子,Reactor模式,重点理解key.attach, jar文件里包含了源代码 1,运行server.bat启动服务器,可以打开编辑,修改端口号 ...

Global site tag (gtag.js) - Google Analytics