基于embedded jetty server的websocket开发

来源:互联网 发布:vb.net 用户控件 编辑:程序博客网 时间:2024/05/01 17:17
基于embedded jetty server的websocket开发

websocket提供一种在浏览器和服务器之间的全双工通信(full-duplex),替代了传统的轮询(polling)做法。目前,在一些web-base的富文本编辑器中有广泛的应用,例如Etherpad,石墨文档,有道云笔记等。具体的关于websocket的定义请参见:http://baike.baidu.com/view/3623887.htmhttps://en.wikipedia.org/wiki/WebSocket。下文是一个基于embedded jetty server的websocket开发的实例,供大家参考。

基本架构:
浏览器(javasscript) --(websocket with ws/wss)--> nginx --(websocket with ws/wss)--> embedded Jetty Server

服务端开发:
关于Jetty Server的介绍,请参见http://www.eclipse.org/jetty/。以下是一些实际的使用经验和技巧,其中包括:
建立服务器端链接侦听(包括ws和wss),
创建消息处理句柄(其中包括WebSocketServlet和WebSocketAdapter)

  1. 构建server端的websocket链接
本实例采用ServerConnector来建立server端链接侦听。代码示例如下:
HttpConfiguration http_config = new HttpConfiguration();
ServerConnector http = new ServerConnector(
websocketServer, new HttpConnectionFactory(http_config));
http.setHost(serverName);
http.setPort(serverPort);
websocketServer.setConnectors(new Connector[]{http});

以上代码基于ws(相当于http),如果需要建立wss链接(相当于https),需要设置KeyStore,代码示例如下:
HttpConfiguration https_config = new HttpConfiguration();
https_config.setSecureScheme("https");
https_config.setSecurePort(securityPort);
https_config.setSendServerVersion(true);
https_config.setSendDateHeader(false);
https_config.addCustomizer(new SecureRequestCustomizer());

SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(".\\ssl\\keystore");
sslContextFactory.setTrustStorePath(".\\ssl\\keystore");
// key store password when generate the store
sslContextFactory.setKeyStorePassword("testPassword");
sslContextFactory.setExcludeCipherSuites(
"SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
ServerConnector sslConnector = new ServerConnector(websocketServer,
new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
sslConnector.setPort(securityPort);
websocketServer.setConnectors(new Connector[]{sslConnector});

  1. 建立客户端消息处理句柄
本实例采用ServletContextHandler来处理发自客户端(javascript)的消息。注:同时引入ContextHandlerCollection,添加一个healthStatus的句柄,来监控jettyServer的运行状态。示例代码如下:
// Add health contextHandler
ContextHandler healthHandler = createHealthStatusHandler();

// Add websocket contextHandler
ServletContextHandler websocketHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
websocketHandler.setContextPath("/");
ServletHolder wsHolder = new ServletHolder(
"collabWebsocket",
new TestCollabSocketServlet());
websocketHandler.addServlet(wsHolder, "/");

// merge two contextHandlers
ContextHandlerCollection handlers = new ContextHandlerCollection();
handlers.setHandlers(new Handler[]{websocketHandler, healthHandler});
websocketServer.setHandler(handlers);

  1. 实现WebSocket Serverlet和Adapter:
public class TestCollabSocketServlet extends WebSocketServlet {

public TestCollabSocketServlet() {
}

@Override
public void configure(WebSocketServletFactory factory) {
factory.register(TestCollabSocketAdapter.class);
}
}
public class TestCollabSocketAdapter extends WebSocketAdapter{
public void onWebSocketClose(int statusCode, String reason){
// 处理关闭事件
}
public void onWebSocketConnect(Session websocketSession) {
// 处理链接事件
}
public void onWebSocketText(String msgText) {
// 处理接收到的消息
}
}


客户端(javascript开发):
  1. 建立和server的链接:
// 这个URL类似 ws://richEditor.com/collab 或者wss://richEditor.com/collab
that._websocket = new WebSocket(websocketURL);
  1. 注册websocket事件,包括open,close,error和message
that._websocket.onopen = that.onOpen.bind(that);
that._websocket.onclose = that.onClose.bind(that);
that._websocket.onmessage = that.onMessage.bind(that);
that._websocket.onerror = that.onError.bind(that);
onOpen: function() {
// 处理链接打开事件
},
onClose: function() {
// 处理链接关闭事件
},
onMessage: function() {
// 处理接受的消息
},
onError: function() {
// 处理链接失败事件
},
总结:
整体来说,这套代码实现相对简单,对于百人级别的并发也可以从容处理。建议:
1, 对于wss的支持,只需要实现从客户端到nginx这一层即可,nginx和Jetty Sever基本同处于内网,可以使用ws连接。
2,可以对传送消息进行一定的压缩,来降低对于带宽的依赖
3,实现自定义的ping/pong消息,用于保证web socket长连接的持续有效(nginx默认会关闭1分钟内没有消息通信的链接)

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 俩人打仗了对方想讹我怎么办 环世界模组装多了打不开怎么办 手机百度云视频播放画面太小怎么办 ps文件说数据似乎已经损坏怎么办 百度云中的压缩包下载的很慢怎么办 游戏压缩出现未知错误或损坏怎么办 百度云里的压缩包解压后损坏怎么办 联创打印时显示压缩文件失败怎么办 电脑的软件打开出现未知格式怎么办 图片只突出人物边上全黑怎么办 合金机兵存档密码忘了怎么办 手机网页验证码无法加载插件怎么办 绝地求生次激战场机型不支持怎么办 木茷生存中文版安装包损坏了怎么办 手机下载软件显示安装包损坏怎么办 不小心把qq图片删了怎么办 奶水不足宝宝不好好吸奶怎么办 膀胱切除前列腺切除阴茎不硬怎么办 小孩的睾丸睾丸碰肿了怎么办 怎么判断小孩子的睾丸没下来怎么办 怀孕39周腰酸屁股酸疼该怎么办 我儿子18岁睾丸筋鼓起来怎么办 去医院检查说精子跑的慢怎么办 多囊卵巢综合症引起屁股增大怎么办 蚊子咬了肿了挠破了流水怎么办 血糖高引发的睾丸一直烂怎么办? 被洪水淹过的猪后期怎么办 做睾丸阴囊彩超阴茎突然勃起怎么办 阴茎冠状沟皮肤感染总不愈合怎么办 不小心咬到孩子破皮了怎么办 小孩子不小心碰到脸黑了一块怎么办 眼睛不小心碰到了里面红了怎么办 八个月宝宝睾丸还沒掉下来怎么办 孩子背部皮肤有一块皮肤很脏怎么办 洗浴种心搓背老板不给发工资怎么办 半个月小鸡屁骨下垂眼睛紧闭怎么办 在学校走廊把老师撞倒了怎么办 裤衩给孩子买的有点肥怎么办 到交警队立案后医疗费没了怎么办 交警扣车车里的贵重东西没了怎么办 睾丸内囊肿割了又长怎么办