`
kree
  • 浏览: 130277 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java非阻塞聊天室源码 Client

阅读更多
//client
public class NBChatClient {
    private static final String CMD_QUIT = "/quit";
    
    private Selector sel;
    private SocketChannel socket;
    private boolean feedback = false;
    private boolean loginSeccess = false;
    private boolean active = true;
    
    private Object oLogin = new Object();
    private ByteBuffer buf = ByteBuffer.allocate(128);
    private static Properties props = new Properties();
    NBChatClient(String fName) {
        initConfig(fName);
        initClient();
        start();
    }
    
    private static void initConfig(String fName) {
        try {
            InputStream in = NBChatServer.class.getClassLoader().getResourceAsStream(fName);
            props.load(in);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }
    
    private void initClient() {
        String ipStr = props.getProperty(NBChatServer.key_ip);
        String portStr = props.getProperty(NBChatServer.key_port);
        
        try {
            sel = Selector.open();
            this.socket = SocketChannel.open();
            InetAddress ip = InetAddress.getByName(ipStr);
            InetSocketAddress remote = new InetSocketAddress(ip, Integer.parseInt(portStr));
            this.socket.connect(remote);
            this.socket.configureBlocking(NBChatServer.NON_BLOCKING);
            socket.register(sel, SelectionKey.OP_READ);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }    
    private void start() {
        //create a new thread to read message from server.
        new Thread() {
            public void run() {
               
                int readyCount = 0;
                while (active) {
                    try {
                        readyCount = sel.select();
                    } catch (IOException e) {
                        if (sel.isOpen())
                            continue;
                        else
                            e.printStackTrace();
                    }
                    if (readyCount == 0)
                        continue;
                    Set readyKeys = sel.selectedKeys();
                    Iterator keys = readyKeys.iterator();
                    while (keys.hasNext()) {
                        SelectionKey key = (SelectionKey) keys.next();
                        if (!key.isValid())
                            continue;
                        keys.remove();
                        try {
                            if (key.isReadable()) {
                                SocketChannel socket = (SocketChannel) key.channel();
                                buf.clear();
                                socket.read(buf);
                                String input = ChatUtil.decode(buf);
                                
                                //如果已经授权,则直接输出信息。
                                if (loginSeccess) {
                                    System.out.println(input);
                                } 
                                //如果没有登录, 且返回信息为授权登录, 则将登录旗标置为true, 并notify主线程。
                                else if (NBChatServer.LOGIN_OK.equals(input)) {
                                    System.out.println("-------------------------------------------- Welcome ------------------------------------ ");
                                    System.out.println("---------------------------------Non Blocking Chat Program------------------------------- ");
                                    System.out.println("----------------------------------------Author: ChenLinping ----------------------------- ");
                                    System.out.println("------------------------------------------------------------------------------------------");
                                    feedback = loginSeccess = true;
                                    
                                    
//                                    //用sleep保证此线程的notify在main线程的wait之后.
//                                    //如果没有这个sleep,则可能发生先notify再wait的情况,则mail线程将一直等待oLogin的锁而阻塞。
//                                    try {
//                                        Thread.sleep(100);
//                                    } catch (InterruptedException e) {
//                                        e.printStackTrace();
//                                    }
                                    
                                    synchronized (oLogin) {
                                        oLogin.notifyAll();
                                    }
                                } 
                                //否则输出permission denied信息。
                                else {
                                    System.out.println("Permission denied~");
                                    feedback = true;
//                                    try {
//                                        Thread.sleep(100);
//                                    } catch (InterruptedException e) {
//                                        e.printStackTrace();
//                                    }
                                    
                                    synchronized (oLogin) {
                                        oLogin.notifyAll();
                                    }
                                }
                            }
                        } catch (IOException e) {
                            System.out.println("You have disconnected!");
                            key.cancel();
                            try {
                                key.channel().close();
                            } catch (IOException e1) {
                                e1.printStackTrace();
                            }
                        }
                    }
                }
            }
        }.start();
    }
    private void handleMsg(String s) throws IOException {
        if (CMD_QUIT.equals(s)) {
            this.active = false;
            socket.close();
            System.exit(-1);
        } else
        socket.write(ByteBuffer.wrap(s.getBytes()));
    }
    private void doLogin(NBChatClient client, BufferedReader input) throws IOException {
        while (!client.loginSeccess) {
            System.out.print("user:");
            String user = input.readLine();
            System.out.print("pass:");
            String pass = input.readLine();
            
            client.handleMsg("/login:"+user+"/"+pass);
            
            //可能存在的一种情况是:程序运行到这里,mail线程还没有block,而server已经响应了,告知client登录成功或失败。这种情况下,则不需要block mail线程。
            //如果是登录成功,则不需要block线程,而应该直接进入聊天。
            //如果是登录失败,也不需要block线程,而应该直接让用户重新登录。
            while (!client.feedback) {
                //输入登录信息后,阻塞main线程,等待系统验证,如果验证成功,则可以开始聊天。
                synchronized (client.oLogin) {
                    try {
                        client.oLogin.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    public static void main(String[] args) {
        NBChatClient client = new NBChatClient(args[0]);
        try {
            BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
            
            client.doLogin(client, input);
            
            String s;
            while ((s = input.readLine()) != null)
                client.handleMsg(s);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
} 

 

分享到:
评论

相关推荐

    java nio聊天室源码

    在这个“java nio聊天室源码”项目中,我们可以看到如何使用NIO构建一个实时、高效的多人在线聊天应用。 首先,我们要理解Java NIO的基本概念。NIO包括以下关键组件: 1. **通道(Channels)**:通道是数据传输的...

    JAVA基于Netty实现的聊天室

    【Java基于Netty实现的聊天室】是一种使用Java编程语言并借助Netty框架构建的实时通信应用。Netty是一个高性能、异步事件驱动的网络应用框架,为开发高并发、低延迟的网络应用提供了强大的支持。这个简易聊天室项目...

    java NIO 学习 聊天室程序 (3)

    在这个“Java NIO 学习 聊天室程序”项目中,我们将深入探讨NIO如何用于创建一个聊天室程序。这个程序可能包含以下几个关键部分: 1. **服务器端**:服务器端使用NIO的ServerSocketChannel监听客户端连接。当新的...

    java源码:java Socket通信实现.rar

    - 使用NIO(New IO)或NIO.2可以实现非阻塞I/O,提升服务器的并发能力。 - 安全性方面,SSL/TLS协议可以为Socket通信提供加密保护,防止数据被窃取。 通过学习并实践这个"java Socket通信实现"的源码,你可以深入...

    java Socket通信实现源码示例

    Java Socket通信广泛应用于各种网络应用,如聊天室、文件传输、在线游戏等。在实际开发中,我们可能会结合线程池、NIO(非阻塞I/O)等技术来优化性能。 九、源码示例 这里提供一个简单的Java Socket通信的服务器端...

    java socket

    Java Socket是Java编程语言中用于网络通信的...通过理解Socket的工作原理,我们可以创建自定义的网络应用,如聊天室、文件传输等。在MyEclipse中,你可以直接导入提供的源码,通过运行和调试来加深对Socket通信的理解。

    socket编程实现简单私聊群聊源码

    在Java中,可以使用多线程或者NIO(非阻塞I/O)来处理并发连接。 在Socket编程中,错误处理至关重要,如连接失败、数据传输异常等都需要妥善处理。此外,为了保证聊天应用的可用性和稳定性,还需要考虑关闭连接的...

    netty-socketio-1.6.5.zip

    开发者可以使用熟悉的Java编程语言,享受到Socket.IO提供的实时双向通信特性,这对于构建实时应用,如聊天室、协作工具、在线游戏等非常有用。 在解压后的文件"netty-socketio-master"中,通常会包含以下内容: 1....

Global site tag (gtag.js) - Google Analytics