1. 程式人生 > >Netty實現帶UI客戶端伺服器聊天功能

Netty實現帶UI客戶端伺服器聊天功能

最近有點閒,用Netty這個非同步框架寫了個聊天功能,也算是對Java語言的一個回顧:

      現有的例子總是使用回撥去處理讀寫,但有時候我們確需要接受來自外界的輸入,比如UI介面的訊息輸入,此時我們就需要提取Channel或者ChannelHandlerContext來進行訊息的傳輸。

      Client端的程式碼比較簡單,提取Connect後的Channel直接進行write就可以寫入訊息:

public class NettyClient {

    private String clientName = "beyondwu";
    public static final int BUFFER_SIZE = 1024;
    public static final int HISTORY_LIST_SIZE = 30;
    private Bootstrap bootstrap;
    private ChannelPipeline chanPipeline;
    private Channel socketChannel;


    private ClientMessageHandler msgHandler;
    private List<String> historyMessage;
    private List<ClientObserver> observerList;

    public NettyClient() {
        historyMessage = new ArrayList<String>();
        observerList = new ArrayList<ClientObserver>();
    }

    public void clientInit() {
        EventLoopGroup group;
        // Configure the client.
        group = new NioEventLoopGroup();
        msgHandler = new ClientMessageHandler(this);
        try {
            bootstrap = new Bootstrap();
            // msgHandler = new ClientMessageHandler();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            chanPipeline = socketChannel.pipeline();
                            chanPipeline.addLast(msgHandler);
                        }
                    });
            // socketChannel = bootstrap.connect(serverIP, serverPort).sync().channel();
        } catch (Exception e1) {
            e1.printStackTrace();
        }

    }


    public String getMessages() {
        String messages;
        Iterator<String> iter = historyMessage.iterator();
        messages = "";
        while (iter.hasNext()) {
            messages += iter.next();
            messages += "\r\n";
        }
        return messages;
    }

    public int connServer(String IP, Integer port) {
        // Start the client.
        ChannelFuture chanFuture;
        try {
            chanFuture = bootstrap.connect(IP, port).sync();
            socketChannel = chanFuture.channel();
            // Wait until the connection is closed.
            System.out.println("connect");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 1;
    }

    public void sendMsg(String msg) {
        String newMessage;
        //Send to Server
        ByteBuf sendMsg = Unpooled.buffer(BUFFER_SIZE);
        sendMsg.writeBytes(msg.getBytes());
        System.out.println("Going to Send: " + msg);
        socketChannel.writeAndFlush(sendMsg);
        newMessage = clientName + ": " + msg;
        updateMsg(newMessage);
    }

    public void updateMsg(String msg) {
        if (historyMessage.size() > HISTORY_LIST_SIZE)
            historyMessage.remove(0);
        historyMessage.add(msg);
        notifyObserver();
    }

    public void register(ClientObserver observer) {
        observerList.add(observer);
    }

    public void notifyObserver() {
        Iterator<ClientObserver> iter = observerList.iterator();
        while (iter.hasNext()) {
            iter.next().update();//獲得各Observer
        }
    }
}
     對於伺服器端,由於需要對連線進行監聽,所以特定開了兩個執行緒,一個執行緒負責連線,一個負責資料的讀寫,這樣保證訊息不會阻塞。另外採用了BlockingQueue進行訊息的阻塞讀取,這樣等待來自UI的資料傳輸。
class BindThread extends Thread {
    NettyServer ntyServer;

    public BindThread(NettyServer server) {
        this.ntyServer = server;
    }

    public void run() {
        try {
            ntyServer.serverInit();
        } catch (SSLException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        }
    }
}

public class MessageWritenThread implements Runnable, ServerObserver {
    ServerUI frontServer;
    NettyServer nettyServer;

    public MessageWritenThread(ServerUI server) {
        frontServer = server;
        nettyServer = new NettyServer();
        nettyServer.registerObserver(this);
        new BindThread(nettyServer).start();
        //new Thread(this).start();
    }

    @Override
    public void run() {
        //nettyServer.serverInit();
        while (true) {
            String sendMsg = "";
            try {
                System.out.println("now send msg: " + sendMsg);
                sendMsg = frontServer.getSendBuffer().take();
                System.out.println("after now send msg: " + sendMsg);
                nettyServer.sendMsg(sendMsg);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //nettyServer.(sendMsg);
        }
    }

    @Override
    public void update() {//can delegate
        frontServer.getContentArea().setText(nettyServer.getMessages());
    }
}

介面如下:


有些細節就沒有更多的時間去考慮了,主要為了練習其中的部分api的使用。更多程式碼請訪問我的github:

相關推薦

Netty實現UI客戶伺服器聊天功能

最近有點閒,用Netty這個非同步框架寫了個聊天功能,也算是對Java語言的一個回顧:       現有的例子總是使用回撥去處理讀寫,但有時候我們確需要接受來自外界的輸入,比如UI介面的訊息輸入,此時我們就需要提取Channel或者ChannelHandlerContext

實現ECHO的客戶伺服器程式設計(多執行緒處理)

伺服器的主要流程: 設定一個埠(ServerSocket)->客戶端連線(.accept())->獲得從客戶端來的資料流->將該資料流到輸出流中 客戶端的主要流程: 設定bufferreader輸入流->連線上埠->獲得從伺服器端來的資料流

曹工雜談:花了兩天時間,寫了一個netty實現的http客戶,支援同步轉非同步和連線池(1)--核心邏輯講解

# 背景 先說下寫這個的目的,其實是好奇,dubbo是怎麼實現同步轉非同步的,然後瞭解到,其依賴了請求中攜帶的請求id來完成這個連線複用;然後我又發現,redisson這個redis客戶端,底層也是用的netty,那就比較好奇了:netty是非同步的,上層是同步的,要拿結果的,同時呢,redis協議也不可能

通過python實現TCP在客戶伺服器上的單(多)執行緒的程式設計

1、只支援一個客戶端訪問 伺服器: from socket import * address='127.0.0.1' #監聽哪些網路 127.0.0.1是監聽本機 0.0.0.0是監聽整個網路 port=12345 #監聽自己的哪個埠 buffsize=

Netty 一個非阻塞的客戶/伺服器框架

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

(QT) C++ 版本IM通訊軟體(客戶+伺服器文字聊天、檔案斷點續傳、線上使用者搜尋)

緊接著上一節課程,這次的作業是要求實現一個簡易版的“QQ”,可支援“軟體需求”所列出的功能。當時由於圖方便便選擇了QTCPSocket進行整個過程的通訊(事後才知道有多坑)。服務端介面比較簡單,就幾個按鈕一個進度條,主要在客戶端實現了基本的功能和介面。整個學習和

python網路程式設計(TCP客戶/伺服器實現

下面的程式實現的功能:客戶端發來訊息,伺服器端加上時間戳返回給使用者 伺服器端: from socket import * from time import ctime import os p

基於TCP協議實現Linux下客戶伺服器之間的通訊,實現多執行緒、多程序伺服器

TCP是TCP/IP協議族中一個比較重要的協議,這是一種可靠、建立連結、面向位元組流的傳輸,工作在傳輸層。和TCP相對的不可靠、無連結、面向資料報的協議UDP,瞭解UDP客戶端與伺服器之間通訊請戳UDP協議實現的伺服器與客戶端通訊 TCP協議建立連線 首

socket實現多個客戶連線在一個伺服器

1、使用socekt通訊一般步驟     1)伺服器端:socker()建立套接字,繫結(bind)並監聽(listen),用accept()等待客戶端連線。     2)客戶端:socker()建立套接字,連線(connect)伺服器,連線上後使用send()和recv(

linux下socket實現多個客戶伺服器的通訊

學習完《UNIX環境高階程式設計》套接字一章的內容之後,自己實現了單個客戶端與伺服器的通訊程式,後面想想要是多個客戶端如何與伺服器通訊呢?這就有了這篇文章。 伺服器端程式: #include<stdio.h> #include <stdlib.h&g

Linux----網路程式設計(TCP網路通訊客戶伺服器程式設計實現多程序)

1、伺服器ser.c 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <assert.h> 5 #in

LInux中利用執行緒實現多個客戶伺服器進行通訊

上一篇博文講了如何利用子程序實現多個客戶端和伺服器端進行通訊, 那麼,這一篇部落格就來實現一下如何利用執行緒實現多個客戶端和伺服器端進行通訊 程式碼實現: ser1.c #include <

如何使用C實現MQTT+TLS客戶程式(1)--使用mosquitto搭建MQTT伺服器

前言 這是一個使用C語言實現的MQTT/TLS的客戶端程式,主要應用在各類嵌入式產品。如果想使用在Android裝置上,讀者可以參考Paho mqtt。 簡單介紹MQTT MQTT遙測傳輸(MQ Telemetry Transport,MQT

TCP客戶/伺服器網路程式設計------多程序併發模型(附帶實現

多程序併發模型相比同步阻塞迭代模型,多程序併發模型可以避免是程式阻塞在read系統呼叫上。如果沒有客戶端來建立連線,則會阻塞在accept處。一旦某個客戶端連線建立起來,則立即開啟一個新的程序來處理與這個客戶的資料互動。避免程式阻塞在read呼叫,而影響其他客戶端的連線。缺陷

第一個corba 程式 實現客戶伺服器通訊 JACORB

JacORB的應用開發一般分為以下五步: 1.寫IDL介面定義編譯IDL 2.介面定義生成Java類 3.實現步驟2中生成的介面 4.寫伺服器啟動類,並註冊到ORB 5.寫客戶端去獲取服務物件引用 2) 在系統環境變數中設定

python實現ftp(客戶

index 登錄 容器 socket per add gbk 默認值 interact 該文檔為用python3實現ftp上傳下載等功能。 1 import optparse 2 import socket 3 import json,os 4 import sh

java在線聊天項目0.4版本 制作服務接收連接,客戶連接功能 新增客戶窗口打開時光標指向下邊文本域功能,使用WindowListener監聽WindowAdapter

內部 frame visible [] one exit eve awt dap 建一個服務端類ChatServer,用於設置端口接收連接 package com.swift; import java.io.IOException; import java.net.Se

使用多線程實現多個客戶與服務通信1

runnable system 處理異常 封裝 端口被占用 直接 客戶端連接 i++ 應用程序 Server.java package socket; import java.io.BufferedReader;import java.io.IOException;impo

Netty(二)建立客戶

1、建立的工程目錄如下:      2、客戶端: (1)客戶端時序圖:   (2)編碼流程: 建立Bootstrap例項 設定EventLoop 指定Channel型別 option配置 b