您的位置:首页 > 产品设计 > UI/UE

Netty实现带UI客户端服务器聊天功能

2016-03-02 21:54 483 查看
最近有点闲,用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:https://github.com/wcwu/NettyChat
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: