怎么用netty搭建一个netty websocket 性能的java客户端

WebSocket不同版本的三种握手方式以及一个Netty实现JAVA类
- ITeye技术网站
博客分类:
一、WebSocket不同版本的三种握手方式
WebSocket是HTML5中的新特性,应用也是非常的广泛,特别是用户WEB端与后台服务器的消息通讯,如阿里的WEBWW就是使用的 WebSocket与后端服务器建立长连接进行的通讯。目前WebSocket还处于发展当中,就目前的发展过程而言,WebSocket现在不同的版 本,有三种不同的握手方式:
1、基于Flash的WebSocket通讯,使用场景是IE的多数版本,因为IE的多数版本不都不支持WebSocket协议,以及FF、CHROME等浏览器的低版本,还没有原生的支持WebSocket,可以使用FLASH的WebSocket实现进行通讯:
浏览器请求:
GET /ls HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
服务器回应:
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin:
WebSocket-Location: ws:///ls
如果客户端没有发送Origin请求头,则客户端不需要返回,如果客户端没有发送WebSocket-Protocol请求头,服务端也不需要返回;服务端唯一需要组装返回给客户端做为校验的就是WebSocket-Location请求头,拼装一个websocket请求的地址就可以了。
这种方式,是最老的一种方式,连一个安全Key都没有,服务端也没有对客户的请求做加密性校验。
2、第二种握手方式是带两个安全key请求头的,结果以md5加密,并放在body中返回的方式,参看如下示例:
浏览器请求:
GET /demo HTTP/1.1
Connection: Upgrade
Sec-WebSocket-Key2:
Sec-WebSocket-Protocol: sample
Upgrade: WebSocket
Sec-WebSocket-Key1: 4 @1
46546xW%0l 1 5
服务器回应:
HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin:
Sec-WebSocket-Location: ws:///demo
Sec-WebSocket-Protocol: sample
8jKS’y:G*Co,Wxa-
在请求中的“Sec-WebSocket-Key1”, “Sec-WebSocket-Key2”和最后的“^n:ds[4U”都是随机的,服务器端会用这些数据来构造出一个16字节的应答。
把第一个Key中的数字除以第一个Key的空白字符的数量,而第二个Key也是如此。然后把这两个结果与请求最后的8字节字符串连接起来成为一个字符串,服务器应答正文(“8jKS’y:G*Co,Wxa-”)即这个字符串的MD5 sum。
3、第三种是带一个安全key的请求,结果是先以“SHA-1”进行加密,再以base64的加密,结果放在Sec-WebSocket-Accept请求头中返回的方式:
浏览器请求:
GET /ls HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Origin:
Sec-WebSocket-Key: 2SCVXUeP9cTjV+0mWB8J6A==
Sec-WebSocket-Version: 8
服务器回应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: mLDKNeBNWz6T9SxU+o0Fy/HgeSw=
握手的实现,首先要获取到请求头中的Sec-WebSocket-Key的值,再把这一段GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"加到获取到的Sec-WebSocket-Key的值的后面,然后拿这个 字符串做SHA-1 hash计算,然后再把得到的结果通过base64加密,就得到了返回给客户端的Sec-WebSocket-Accept的http响应头的值。
还可以参看我前面专门针对这种协议写的一篇文章:
二、基于Netty实现JAVA类
为了支持以上提到的三种不同版本的websocket握手实现,服务端就需要针对这三种情况进行相应的处理,以下是一段基于netty实现的java代码,一个完整的WebSocketHelper实现:
import java.io.UnsupportedEncodingE
import java.security.MessageD
import java.security.NoSuchAlgorithmE
import org.jboss.netty.buffer.ChannelB
import org.jboss.netty.buffer.ChannelB
import org.jboss.netty.handler.codec.http.DefaultHttpR
import org.jboss.netty.handler.codec.http.HttpH
import org.jboss.netty.handler.codec.http.HttpHeaders.N
import org.jboss.netty.handler.codec.http.HttpR
import org.jboss.netty.handler.codec.http.HttpR
import org.jboss.netty.handler.codec.http.HttpResponseS
import org.jboss.netty.handler.codec.http.HttpV
public class WebSocketHelper {
private final static String SEC_WEBSOCKET_KEY
= "Sec-WebSocket-Key";
private final static String SEC_WEBSOCKET_ACCEPT
= "Sec-WebSocket-Accept";
private final static String Sec_WebSocket_Version = "Sec-WebSocket-Version";
public boolean supportWebSocket(HttpRequest req) {
return (HttpHeaders.Values.UPGRADE.equalsIgnoreCase(req.getHeader(HttpHeaders.Names.CONNECTION)) && HttpHeaders.Values.WEBSOCKET.equalsIgnoreCase(req.getHeader(HttpHeaders.Names.UPGRADE)));
public HttpResponse buildWebSocketRes(HttpRequest req) {
String reasonPhrase = "";
boolean isThirdTypeHandshake = Boolean.FALSE;
int websocketVersion = 0;
if (req.getHeader(Sec_WebSocket_Version) != null) {
websocketVersion = Integer.parseInt(req.getHeader(Sec_WebSocket_Version));
if (websocketVersion &= 13
|| (req.containsHeader(Names.SEC_WEBSOCKET_ORIGIN) && req.containsHeader(SEC_WEBSOCKET_KEY))) {
isThirdTypeHandshake = Boolean.TRUE;
if (isThirdTypeHandshake = Boolean.FALSE) {
reasonPhrase = "Switching Protocols";
reasonPhrase = "Web Socket Protocol Handshake";
HttpResponse res = new DefaultHttpResponse(HttpVersion.HTTP_1_1, new HttpResponseStatus(101, reasonPhrase));
res.addHeader(HttpHeaders.Names.UPGRADE, HttpHeaders.Values.WEBSOCKET);
res.addHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.UPGRADE);
if (req.containsHeader(Names.SEC_WEBSOCKET_KEY1) && req.containsHeader(Names.SEC_WEBSOCKET_KEY2)) {
res.addHeader(Names.SEC_WEBSOCKET_ORIGIN, req.getHeader(Names.ORIGIN));
res.addHeader(Names.SEC_WEBSOCKET_LOCATION, getWebSocketLocation(req));
String protocol = req.getHeader(Names.SEC_WEBSOCKET_PROTOCOL);
if (protocol != null) {
res.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, protocol);
String key1 = req.getHeader(Names.SEC_WEBSOCKET_KEY1);
String key2 = req.getHeader(Names.SEC_WEBSOCKET_KEY2);
int a = (int) (Long.parseLong(getNumeric(key1)) / getSpace(key1).length());
int b = (int) (Long.parseLong(getNumeric(key2)) / getSpace(key2).length());
long c = req.getContent().readLong();
ChannelBuffer input = ChannelBuffers.buffer(16);
input.writeInt(a);
input.writeInt(b);
input.writeLong(c);
ChannelBuffer output = null;
output = ChannelBuffers.wrappedBuffer(MessageDigest.getInstance("MD5").digest(input.array()));
} catch (NoSuchAlgorithmException e) {
res.setContent(output);
} else if (isThirdTypeHandshake = Boolean.FALSE) {
String protocol = req.getHeader(Names.SEC_WEBSOCKET_PROTOCOL);
if (protocol != null) {
res.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, protocol);
res.addHeader(SEC_WEBSOCKET_ACCEPT, getSecWebSocketAccept(req));
if (req.getHeader(Names.ORIGIN) != null) {
res.addHeader(Names.WEBSOCKET_ORIGIN, req.getHeader(Names.ORIGIN));
res.addHeader(Names.WEBSOCKET_LOCATION, getWebSocketLocation(req));
String protocol = req.getHeader(Names.WEBSOCKET_PROTOCOL);
if (protocol != null) {
res.addHeader(Names.WEBSOCKET_PROTOCOL, protocol);
private String getWebSocketLocation(HttpRequest req) {
return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + req.getUri();
private String getSecWebSocketAccept(HttpRequest req) {
String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
String key = "";
key = req.getHeader(SEC_WEBSOCKET_KEY);
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(key.getBytes("iso-8859-1"), 0, key.length());
byte[] sha1Hash = md.digest();
key = base64Encode(sha1Hash);
} catch (NoSuchAlgorithmException e) {
} catch (UnsupportedEncodingException e) {
String base64Encode(byte[] input) {
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
String base64 = encoder.encode(input);
return base64;
private String getNumeric(String str) {
return str.replaceAll("\\D", "");
private String getSpace(String str) {
return str.replaceAll("\\S", "");
三、注意事项
不同版本的WebSocket标准,编码和解码的方式还有所不同,在第一种和第二种WebSocket协议标准中,使用Netty自带的Encoder和Decoder即可:
org.jboss.netty.handler.codec.http.websocket.WebSocketFrameEncoder org.jboss.netty.handler.codec.http.websocket.WebSocketFrameDecoder
而如果要支持第三种实现标准,Netty目前官方还不支持,可以到github中找到实现的Encoder及Decoder:
不过,它的实现有一点问题,就是没有处理客户端主动发起的WebSocket请求断开,既客户端主动发起opcode为8的请求,不过它还是有预留的,找到这个类:
Hybi10WebSocketFrameDecoder
的包含这以下内容的行:
} else if (this.opcode == OPCODE_CLOSE) {
在其中插入:
return new DefaultWebSocketFrame(0x08, frame);
然后在你的实现子类中增加如下的代码判断即可:
if (frame.getType() == 0x08) {
浏览: 273462 次
来自: 广州
推荐一款轻量开源的支付宝组件:https://github.c ...
太好了,非常有用,谢谢分享~
http://www.atool.org/json2javab ...
这样只要是手机登录了微信的用户。扫描二维码后都可以登录进入网站 ...
好文章,收藏~\(≧▽≦)/~啦啦啦websocket 基于netty封装的 ,用java实现,前后台简单例子 Develop 238万源代码下载-
&文件名称: websocket
& & & & &&]
&&所属分类:
&&开发工具: Java
&&文件大小: 1122 KB
&&上传时间:
&&下载次数: 1
&&提 供 者:
&详细说明:基于netty封装的websocket,用java实现,前后台简单例子-
Based netty package websocket, using java, front desk simple example
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&websocket&&.........\.classpath&&.........\.project&&.........\.settings&&.........\.........\.jsdtscope&&.........\.........\org.eclipse.jdt.core.prefs&&.........\.........\org.eclipse.wst.jsdt.ui.superType.container&&.........\.........\org.eclipse.wst.jsdt.ui.superType.name&&.........\src&&.........\...\com&&.........\...\...\websocket&&.........\...\...\.........\CustomTextFrameHandler.java&&.........\...\...\.........\WebSocketServer.java&&.........\...\...\.........\WebSocketServerPipelineFactory.java&&.........\...\listener&&.........\...\........\WebListener.java&&.........\WebContent&&.........\..........\index.jsp&&.........\..........\js&&.........\..........\..\jquery.min.js&&.........\..........\..\websocket.js&&.........\..........\META-INF&&.........\..........\........\MANIFEST.MF&&.........\..........\WEB-INF&&.........\..........\.......\classes&&.........\..........\.......\.......\com&&.........\..........\.......\.......\...\websocket&&.........\..........\.......\.......\...\.........\CustomTextFrameHandler.class&&.........\..........\.......\.......\...\.........\WebSocketServer.class&&.........\..........\.......\.......\...\.........\WebSocketServerPipelineFactory.class&&.........\..........\.......\.......\listener&&.........\..........\.......\.......\........\WebListener.class&&.........\..........\.......\lib&&.........\..........\.......\...\netty-3.6.0.Final.jar&&.........\..........\.......\...\servlet-api-5.5.23.jar&&.........\..........\.......\web.xml&&.........\WebRoot&&.........\.......\WEB-INF&&.........\.......\.......\classes&&.........\.......\.......\.......\com&&.........\.......\.......\.......\...\websocket&&.........\.......\.......\.......\...\.........\CustomTextFrameHandler.class&&.........\.......\.......\.......\...\.........\WebSocketServer.class&&.........\.......\.......\.......\...\.........\WebSocketServerPipelineFactory.class&&.........\.......\.......\.......\listener&&.........\.......\.......\.......\........\WebListener.class
&近期下载过的用户:
&相关搜索:
&输入关键字,在本站238万海量源码库中尽情搜索:
&[] - 使用thrift、websocket在javascript和cpp之间建立rpc调用机制。 如果要使用js+html来写界面,cpp来写底层业务逻辑,这就非常有用了。 当然,如果底层不用cpp来写,也可以参考本代码的js对thrift的rpc包装。
&[] - 在线聊天室,实现实时用户间的登陆聊天功能,利用websocketnetty&websocket&做的web聊天小应用
本文中,我用的netty4.0,服务器部分从官网example上弄下来的,经过部分修改。
小应用仅简单实现了聊天功能,供讨论学习之用。
Java工具:Gson、netty-4.0.19,
js框架:jquery-1.9.1.min.js
测试的时候先启动服务,WebSocketServer有main函数,之后可以在一个浏览器打开多个一下提供的网页,页面会自动获取已连接的客户端,选择相应客户端便可进行聊天了。
这个小应用肯定还存在好些问题,希望能相互学习交流
一、服务器部分
(1)WebSocketServer.java
package com.gecq.websocket.
import io.netty.bootstrap.ServerB
import io.netty.channel.C
import io.netty.channel.EventLoopG
import io.netty.channel.nio.NioEventLoopG
io.netty.channel.socket.nio.NioServerSocketC
public class WebSocketServer {
public WebSocketServer(int port) {
this.port =
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerChannelGroup channels= new ServerChannelGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new WebSocketServerInitializer(channels));
Channel ch = b.bind(port).sync().channel();
System.out.println("Web socket server started at port " +
System.out
.println("Open your browser and navigate to
http://localhost:"
+ port + '/');
ch.closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
public static void main(String[] args) throws Exception
if (args.length & 0) {
port = Integer.parseInt(args[0]);
port = 8080;
new WebSocketServer(port).run();
(2)WebSocketServerInitializer.java
package com.gecq.websocket.
import io.netty.channel.ChannelI
import io.netty.channel.ChannelP
import io.netty.channel.socket.SocketC
import io.netty.handler.codec.http.HttpObjectA
import io.netty.handler.codec.http.HttpServerC
public class WebSocketServerInitializer extends
ChannelInitializer {
ServerChannelG
public WebSocketServerInitializer(ServerChannelGroup
channels){
this.channels=
public void initChannel(SocketChannel ch) throws Exception
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("codec-http", new HttpServerCodec());
pipeline.addLast("aggregator", new
HttpObjectAggregator(65536));
pipeline.addLast("handler", new
WebSocketServerHandler(this.channels));
(3)WebSocketServerHandler.java
package com.gecq.websocket.
import io.netty.buffer.ByteB
import io.netty.buffer.U
import io.netty.channel.C
import io.netty.channel.ChannelF
import io.netty.channel.ChannelFutureL
import io.netty.channel.ChannelHandlerC
import io.netty.channel.SimpleChannelInboundHand
io.netty.handler.codec.http.DefaultFullHttpR
import io.netty.handler.codec.http.FullHttpR
import io.netty.handler.codec.http.FullHttpR
io.netty.handler.codec.http.websocketx.CloseWebSocketF
io.netty.handler.codec.http.websocketx.PingWebSocketF
io.netty.handler.codec.http.websocketx.PongWebSocketF
io.netty.handler.codec.http.websocketx.TextWebSocketF
io.netty.handler.codec.http.websocketx.WebSocketF
io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerF
import io.netty.util.CharsetU
import java.util.HashM
import java.util.M
import java.util.S
import java.util.logging.L
import java.util.logging.L
import com.google.gson.G
import static
io.netty.handler.codec.http.HttpHeaders.Names.*;
import static io.netty.handler.codec.http.HttpHeaders.*;
import static io.netty.handler.codec.http.HttpMethod.*;
import static
io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.*;
public class WebSocketServerHandler extends
SimpleChannelInboundHandler {
private static final Logger logger = Logger
.getLogger(WebSocketServerHandler.class.getName());
private static final String WEBSOCKET_PATH =
"/websocket";
private WebSocketServerHandshake
private ServerChannelG
public WebSocketServerHandler(ServerChannelGroup channels)
this.channels=
gson = new Gson();
public void channelRead(ChannelHandlerContext ctx, Object
throws Exception {
if (msg instanceof FullHttpRequest) {
handleHttpRequest(ctx, (FullHttpRequest) msg);
} else if (msg instanceof WebSocketFrame) {
handleWebSocketFrame(ctx, (WebSocketFrame) msg);
public void channelReadComplete(ChannelHandlerContext ctx)
throws Exception {
ctx.flush();
private void handleHttpRequest(ChannelHandlerContext
FullHttpRequest req) throws Exception {
// Handle a bad request
if (!req.getDecoderResult().isSuccess()) {
sendHttpResponse(ctx, req, new
DefaultFullHttpResponse(HTTP_1_1,
BAD_REQUEST));
// Allow only GET methods.
if (req.getMethod() != GET) {
sendHttpResponse(ctx, req, new
DefaultFullHttpResponse(HTTP_1_1,
FORBIDDEN));
// Send the demo page and favicon.ico
if ("/".equals(req.getUri())) {
ByteBuf content = WebSocketServerIndexPage
.getContent(getWebSocketLocation(req));
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1,
res.headers().set(CONTENT_TYPE, "text/
charset=UTF-8");
setContentLength(res, content.readableBytes());
sendHttpResponse(ctx, req, res);
if ("/favicon.ico".equals(req.getUri())) {
FullHttpResponse res = new
DefaultFullHttpResponse(HTTP_1_1,
NOT_FOUND);
sendHttpResponse(ctx, req, res);
// Handshake
WebSocketServerHandshakerFactory wsFactory = new
WebSocketServerHandshakerFactory(
getWebSocketLocation(req), null, false);
handshaker = wsFactory.newHandshaker(req);
if (handshaker == null) {
WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
handshaker.handshake(ctx.channel(), req);
private void handleWebSocketFrame(ChannelHandlerContext
WebSocketFrame frame) {
// Check for closing frame
if (frame instanceof CloseWebSocketFrame) {
handshaker.close(ctx.channel(),
(CloseWebSocketFrame) frame.retain());
if (frame instanceof PingWebSocketFrame) {
ctx.channel().write(
new PongWebSocketFrame(frame.content().retain()));
if (!(frame instanceof TextWebSocketFrame)) {
throw new UnsupportedOperationException(String.format(
"%s frame types not supported",
frame.getClass().getName()));
// Send the uppercase string back.
String request = ((TextWebSocketFrame) frame).text();
Message msg = gson.fromJson(request, Message.class);
if (logger.isLoggable(Level.FINE)) {
logger.fine(String.format("%s received %s", ctx.channel(),
request));
if(msg.getType()==0||msg.getType()==2){
Map all = channels.getAll();
Set keys = all.keySet();
Map temp=new HashMap();
temp.put("type", 0);
Channel c=
for (String k : keys) {
c=all.get(k).getChannel();
temp.put("users", channels.onlineUsers(k));
temp.put("from", c.remoteAddress().toString());
c.writeAndFlush(new
TextWebSocketFrame(gson.toJson(temp)));
}else if(msg.getType()==1){
User u=channels.getById(msg.getTo());
if(u!=null)
u.getChannel().writeAndFlush(new
TextWebSocketFrame(gson.toJson(msg)));
ctx.channel().writeAndFlush(new
TextWebSocketFrame(gson.toJson(new Message(-1,"不在线"))));
private static void sendHttpResponse(ChannelHandlerContext
FullHttpRequest req, FullHttpResponse res) {
// Generate an error page if response getStatus code is not OK
if (res.getStatus().code() != 200) {
ByteBuf buf =
Unpooled.copiedBuffer(res.getStatus().toString(),
CharsetUtil.UTF_8);
res.content().writeBytes(buf);
buf.release();
setContentLength(res, res.content().readableBytes());
// Send the response and close the connection if
necessary.
ChannelFuture f = ctx.channel().writeAndFlush(res);
if (!isKeepAlive(req) || res.getStatus().code() != 200)
f.addListener(ChannelFutureListener.CLOSE);
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause)
throws Exception {
cause.printStackTrace();
ctx.close();
private static String getWebSocketLocation(FullHttpRequest
return "ws://" + req.headers().get(HOST) +
WEBSOCKET_PATH;
protected void channelRead0(ChannelHandlerContext ctx, Object
throws Exception {
public void channelUnregistered(ChannelHandlerContext ctx)
throws Exception {
channels.removeChannel(ctx.channel());
super.channelUnregistered(ctx);
public void channelRegistered(ChannelHandlerContext ctx)
throws Exception {
super.channelRegistered(ctx);
channels.addChannel(ctx.channel());
二、自定义部分
(1)User.java
package com.gecq.websocket.
import io.netty.channel.C
public class User {
public User(){}
public User(Channel channel,String addr,String id){
this.channel=
this.address=
public User(Channel channel,String addr){
this.channel=
this.address=
public User(Channel channel){
this.channel=
this.address=channel.remoteAddress().toString();
this.id=String.format("0xx",channel.hashCode());
public Channel getChannel() {
public void setChannel(Channel channel) {
this.channel =
public String getAddress() {
public void setAddress(String address) {
this.address =
public String getId() {
public void setId(String id) {
(2)Message.java
package com.gecq.websocket.
public class Message {
//0:第一次连接 &
public Message(){}
public Message(int type,String msg){
this.type=
public String getTo() {
public void setTo(String to) {
public String getMsg() {
public void setMsg(String msg) {
this.msg =
public String getFrom() {
public void setFrom(String from) {
this.from =
public int getType() {
public void setType(int type) {
this.type =
(3)ServerChannelGroup.java
package com.gecq.websocket.
import io.netty.channel.C
import java.util.ArrayL
import java.util.HashM
import java.util.L
import java.util.M
import java.util.S
import com.gecq.websocket.utils.JSON;
public class ServerChannelGroup {
private Map userM
public ServerChannelGroup(){
if(userMap==null){
userMap=new HashMap();
public User getById(String id){
return userMap.get(id);
public String addChannel(Channel channel){
String id=String.format("0xx",channel.hashCode());
return addChannel(id,channel);
public String addChannel(String id,Channel channel){
if(!userMap.containsKey(id))
userMap.put(id, new User(channel));
public Map getAll(){
return userM
public String onlineUsers(Channel channel){
String id=String.format("0xx",channel.hashCode());
return onlineUsers(id);
public String onlineUsers(String id){
&Map temp=new HashMap();
&List online=new ArrayList();
&temp.putAll(userMap);
&temp.remove(id);
&Set ks=temp.keySet();
&for(String k:ks){
& online.add(temp.get(k));
&return JSON.filter(null,
Channel.class).toJson(online);
public void removeChannel(Channel channel){
String id=String.format("0xx",channel.hashCode());
removeChannel(id);
public void removeChannel(String id){
userMap.remove(id);
三、网页部分
js脚本部分
$(document).ready(
function() {
ws = new WebSocket("ws://localhost:8080/websocket");
ws.onopen = function(event) {
ws.send("{type:'0'}");
$('#status').text("已连接.");
ws.onmessage = function(event) {
var res = event.
res = $.parseJSON(event.data);
if (res.type == 0) {
$(".users").html("");
var users = $.parseJSON(res.users);
$(".addr").val(res.from);
for ( var i in users) {
$(".users").append(
+ users[i].address + "")
} else if(res.type==1){
$(".chat-msgs").append("
"+res.msg+":"+res.from+"
} else if(res.type==-1){
alert("已下线");
ws.send("{type:'0'}");
ws.onclose = function(event) {
ws.send("{type:'2'}");
$('#status').text(
"服务器已中断.");
$('#msg').keyup(function(e) {
if (e.which == 13) {
sendNumber();
function sendNumber() {
var number = $('#msg').val();
if (number == "") {
ws.send("{type:'1',to:'" + $(".users").val() +
"',from:'"
+ $(".addr").val() + "',msg:'" + number + "'}");
$('#msg').val("");
$(".chat-msgs").append("
我:"+number+"
页面样式部分
text-align:
font-size: 12
.chat-box {
width: 600
min-width: 600
border-radius: 10
box-shadow: 0 0 4px #333;
text-align:
padding: 15
height: 24
.chat-msgs {
height: 300
border: 1px solid #
overflow-y:
padding:10
width: 100%;
height: 100
margin: 0;
padding: 5px 0;
text-indent: 0.3
.chat-msgs .msg-send {
text-align:
margin: 5px 0;
.chat-msgs &.msg {
display: inline-
padding: 5
border-radius: 6
border: 1px solid #888;
.chat-msgs .msg-get {
text-align:
margin: 5px 0;
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 netty socket客户端 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信