WebSocket使用SuperWebSocket结合WindowsService实现实时消息
SuperWebSocket在WebService中的应用
最开始使用是寄托在IIS中,发布之后测试时半个小时就会断开,所以改为WindowsService
1. 新建Windows服务项目【TestWindowsService】,重命名Service1为MyWebSocketService
2. 打开MyWebSocketService设计视图,右键,添加安装程序,自动添加ProjectInstaller.cs。
打开设计视图,选中ServiceInstaller1,右键修改属性:
- ServiceName(服务名):这里改为我们刚重命名的MyWebSocketService
- StartType(启动方式):改为自动启动Automatic
- DelayedAutoStart(延迟加载)
选中serviceProcessInstaller1,右键修改属性:
- Account(账户类型):这里改为LocalSystem
3. 添加安装和卸载文件。注意添加文件请使用ANSI编码。推荐使用EditPlus等工具新建文件,然后通过项目添加现有项。
注意替换TestWindowsService.exe和MyWebSocketService。右键属性,设置复制到输出目录。
Install.bat:
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe TestWindowsService.exe
sc config MyWebSocketService start= auto
Net Start MyWebSocketService
pause
Uninstall.bat
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u TestWindowsService.exe
4. 添加App.config,配置IP和Port。
IP地址为本地连接地址,端口号自定义。确保端口号不被占用。
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="APWebSocketIP" value="192.168.1.199"/>
<add key="APWebSocketPort" value="8200"/>
</appSettings>
</configuration>
5. 修改MyWebSocketService服务代码。
推荐手动加载dll,通过Nuget加载时,添加依赖的Log4net版本与SuperWebSocket中调用的Log4net版本存在冲突。
log4net版本为1.2.11.0
项目右键,管理Nuget程序包,搜索SuperWebSocket,注意作者为Kerry Jiang。
WebSocketServer server;
protected override void OnStart(string[] args)
{
var ip = ConfigurationManager.AppSettings["APWebSocketIP"];
var port = ConfigurationManager.AppSettings["APWebSocketPort"];
//WebSocket服务器端启动
server = new WebSocketServer();
if (!server.Setup(ip, int.Parse(port)))
{
//Debug.Write("WebSocket服务器端启动失败");
//处理启动失败消息
return;
}
//新的会话连接时
server.NewSessionConnected += server_NewSessionConnected;
//会话关闭
server.SessionClosed += server_SessionClosed;
//接收到新的消息时
server.NewMessageReceived += server_NewMessageReceived;
if (!server.Start())
{
//Debug.Write(string.Format("开启WebSocket服务侦听失败:{0}:{1}", server.Config.Ip, server.Config.Port));
//处理监听失败消息
return;
}
}
string KSessionId;
string VSessionId;
Dictionary<string, List<string>> msgDictionary = new Dictionary<string, List<string>>();
private void server_NewMessageReceived(WebSocketSession session, string value)
{
Debug.WriteLine("接收到新的消息:{0} 来自:{1} 时间:{2:HH:MM:ss}", value, session.RemoteEndPoint, DateTime.Now);
if (value.StartsWith("K"))
{
KSessionId = session.SessionID;
//页面已链接
if (!String.IsNullOrEmpty(VSessionId))
SendMsgToRemotePoint(VSessionId, string.Format("考场发来消息:{0}", value));
//页面未链接
else
{
AddMsgToSessionId(VSessionId);
}
}
else if (value.StartsWith("S"))
{
VSessionId = session.SessionID;
//考场已链接
if (!String.IsNullOrEmpty(KSessionId))
SendMsgToRemotePoint(KSessionId, string.Format("学生A发来消息:{0}", value));
//考场已断开
else
{
AddMsgToSessionId(KSessionId);
}
}
}
/// <summary>
/// 添加会话消息
/// </summary>
/// <param name="value"></param>
private void AddMsgToSessionId(string value)
{
if (value != null)
{
//消息列表包含页面会话ID
if (msgDictionary.ContainsKey(value))
{
msgDictionary[value].Add(value);
}
//消息列表不包含页面会话ID
else
msgDictionary.Add(value, new List<string>() { value });
}
}
/// <summary>
/// 会话关闭
/// </summary>
/// <param name="session"></param>
/// <param name="value"></param>
private void server_SessionClosed(WebSocketSession session, SuperSocket.SocketBase.CloseReason value)
{
Debug.WriteLine("会话关闭,关闭原因:{0} 来自:{1} 时间:{2:HH:MM:ss}", value, session.RemoteEndPoint, DateTime.Now);
if (session.SessionID == KSessionId)
SendMsgToRemotePoint(VSessionId, "考场已断开");
else if (session.SessionID == VSessionId)
SendMsgToRemotePoint(KSessionId, "学生A已断开");
}
/// <summary>
/// 新的会话链接
/// </summary>
/// <param name="session"></param>
private void server_NewSessionConnected(WebSocketSession session)
{
Debug.WriteLine("新的会话连接 来自:{0} SessionID:{1} 时间:{2:HH:MM:ss}", session.RemoteEndPoint, session.SessionID, DateTime.Now);
if (msgDictionary.ContainsKey(session.SessionID))
msgDictionary[session.SessionID].ForEach(item => session.Send(item));
}
/// <summary>
/// 发送消息到
/// </summary>
/// <param name="sessionId"></param>
/// <param name="msg"></param>
private void SendMsgToRemotePoint(string sessionId, string msg)
{
var allSession = server.GetAppSessionByID(sessionId);
if (allSession != null)
allSession.Send(msg);
}
6.添加log4net配置文件log4net.config。查看日志。
由于SuperWebSocket已经有日志功能,只需要添加配置文件,即可查看日志。
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="errorAppender" type="log4net.Appender.RollingFileAppender">
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="ERROR" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<File value="Logs\err.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="infoAppender" type="log4net.Appender.RollingFileAppender">
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="INFO" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<File value="Logs\info.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="debugAppender" type="log4net.Appender.RollingFileAppender">
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="DEBUG" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<File value="Logs\debug.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="perfAppender" type="log4net.Appender.RollingFileAppender">
<filter type="log4net.Filter.LevelMatchFilter">
<levelToMatch value="INFO" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<File value="Logs\perf.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="errorAppender" />
<appender-ref ref="infoAppender" />
<appender-ref ref="debugAppender" />
</root>
<logger name="Performance" additivity="false">
<level value="ALL" />
<appender-ref ref="perfAppender" />
</logger>
</log4net>
在html中使用WebSocket
1.首先考虑浏览器兼容问题。一些低版本浏览器不支持。
2.创建websocket对象,设置ip和端口。
var ws;
var url = "ws://192.168.1.199:8200";
$("#btnConnection").click(function () {
if ("WebSocket" in window) {
ws = new WebSocket(url);
}
else if ("MozWebSocket" in window) {
ws = new MozWebSocket(url);
}
else
alert("浏览器版本过低,请升级您的浏览器。\r\n浏览器要求:IE10+/Chrome14+/FireFox7+/Opera11+");
//注册各类回调
ws.onopen = function () {
$("#msg").append("连接服务器成功<br/>");
ws.send("S:学生A已链接");
}
ws.onclose = function () {
$("#msg").append("与服务器断开连接<br/>");
}
ws.onerror = function () {
$("#msg").append("数据传输发生错误<br/>");
}
ws.onmessage = function (receiveMsg) {
$("#msg").append(receiveMsg.data + "<br/>");
}
});
这里模拟一个学生A和考场的交互。
首先连接考场。
接着连接考生。
考场发送消息,通知学生开始考试。
学生接到消息,开始答题。
考试收到考生开始答题消息。
发布
1.首先拷贝TestWebService中的bin\Debug|Release中生成的文件到服务器。通过开始→运行→cmd→ipconfig,查看服务器的本地链接地址(192开头)。修改App.config中的IP和端口号。
2.双击Install.bat文件,等待安装服务。
3.修改html中的WebSocket对象的ip和端口号。这里的ip为服务器固定ip,与WebSocket配置不同。
4.如果涉及到读写文件,请在服务器端类360安全卫士等软件添加信任。
通过Install.bat无法启动时,可以查看本地日志文件和控制面板的事件管理器,定位详细错误。
源代码下载:TestWebSocket.zip
转载请注明出处:http://xcong.cnblogs.com
WebSocket使用SuperWebSocket结合WindowsService实现实时消息的更多相关文章
- PHP Web实时消息后台服务器推送技术---GoEasy
越来越多的项目需要用到实时消息的推送与接收,怎样用php实现最方便呢?我这里推荐大家使用GoEasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送! 浏览器兼容性:GoEasy推送 ...
- Ruby Web实时消息后台服务器推送技术---GoEasy
越来越多的项目需要用到实时消息的推送与接收,怎样用Ruby实现最方便呢?我这里推荐大家使用GoEasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送! 浏览器兼容性:GoEasy推 ...
- vue+websocket+express+mongodb实战项目(实时聊天)
继上一个项目用vuejs仿网易云音乐(实现听歌以及搜索功能)后,发现上一个项目单纯用vue的model管理十分混乱,然后我去看了看vuex,打算做一个项目练练手,又不想做一个重复的项目,这次我就放弃颜 ...
- vue+websocket+express+mongodb实战项目(实时聊天)(二)
原项目地址:[ vue+websocket+express+mongodb实战项目(实时聊天)(一)][http://blog.csdn.net/blueblueskyhua/article/deta ...
- JAVA Web实时消息后台服务器推送技术---GoEasy
---恢复内容开始--- 越来越多的项目需要用到实时消息的推送与接收,我这里推荐大家使用GoEasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送! 浏览器兼容性:GoEasy推送 ...
- 开源实时消息推送系统 MPush
系统介绍 mpush,是一款开源的实时消息推送系统,采用java语言开发,服务端采用模块化设计,具有协议简洁,传输安全,接口流畅,实时高效,扩展性强,可配置化,部署方便,监控完善等特点.同时也是少有的 ...
- node.js中使用socket.io + express进行实时消息推送
socket.io是一个websocket库,包含客户端的js和服务端的node.js,可以在不同浏览器和移动设备上构建实时应用. 一.安装 socket.io npm install socket. ...
- 基于socket.io的实时消息推送
用户访问Web站点的过程是基于HTTP协议的,而HTTP协议的工作模式是:请求-响应,客户端发出访问请求,服务器端以资源数据响应请求. 也就是说,服务器端始终是被动的,即使服务器端的资源数据发生变化, ...
- 【js学习】js连接RabbitMQ达到实时消息推送
js连接RabbitMQ达到实时消息推送 最近在自己捯饬一个网站,有一个功能是需要后端处理完数据把数据发布到MQ中,前端再从MQ中接收数据.但是前端连接MQ又成了一个问题,在网上搜了下资料,点进去一篇 ...
随机推荐
- Keil调试程序如何查看变量
第一个问题:调试时候想实时查看某一变量变化? view 菜单下的 watch windows,全局变量才能查看 比如要查看u8 adcx的值变化,如下: 全速运行后,如下: 无法查看!什么问题? 该变 ...
- [NOI2008] 志愿者招募[流量平衡]
288. [NOI2008] 志愿者招募 ★★★★ 输入文件:employee.in 输出文件:employee.out 简单对比时间限制:2 s 内存限制:512 MB [问题描述] ...
- 170403、java 版cookie操作工具类
package com.rick.utils; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; imp ...
- Python全栈day10(运算符)
一,运算符 + - * . ** % // 二,in 和not in 一个字符串包含多个字符可以通过in判断字符是否属于改字符串 >>> name = "zhangsan& ...
- HDU 2665 Kth number(可持续化线段树)
Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- Spring Data CrudRepository增删改查方法(八)
CrudRepository 的主要方法 long count(); boolean exists(Integer arg0); <S extends StudentPO> S sav ...
- centos下vsftpd不能显示文件,不能创建文件及文件夹
centos下vsftpd登录正常,但不能显示文件,不能创建文件及文件夹 这是由于selinux的机制 通过命令 [root@localhost www]# getsebool -a|grep ftp ...
- Error response from daemon: error creating overlay mount to /var/lib/docker/overlay2
环境:centos7.1 docker run -t -i centos /bin/bash 运行上面的命令开启容器时报错: /usr/bin/docker-current: Error respon ...
- Python 中的匿名函数,你滥用了吗?
概念 我们从一个例子引入. 这里有一个元素为非空字符串的列表,按字符串最后一个字母将列表进行排序.如果原列表是 ['abc', 'g', 'def'],则结果应该是 ['abc', 'def', 'g ...
- Centos配置nginx反向代理8090端口到80端口
下面,我就来说说怎么反向代理自己的项目到默认80端口. 1)安装nginx:yum install nginx -y 2)启动nginx:service nginx start或者systemctl ...