zoukankan      html  css  js  c++  java
  • WebSocket实现简单的在线聊天

    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.NETFrameworkv4.0.30319installutil.exe TestWindowsService.exe
    sc config MyWebSocketService start= auto 
    Net Start MyWebSocketService
    pause

    Uninstall.bat

    %SystemRoot%Microsoft.NETFrameworkv4.0.30319installutil.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配置文件。查看日志。

    由于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="Logserr.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="Logsinfo.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="Logsdebug.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="Logsperf.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("浏览器版本过低,请升级您的浏览器。
    浏览器要求: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中的binDebug|Release中生成的文件到服务器。通过开始运行,查看服务器的本地链接地址(192开头)。修改App.config中的IP和端口号。

    2.双击Install.bat文件,等待安装服务。

    3.修改html中的WebSocket对象的ip和端口号。

    通过Install.bat无法启动时,可以查看本地日志文件和控制面板的事件管理器,定位详细错误

    原文链接:http://www.tuicool.com/articles/jqa6Zb

  • 相关阅读:
    把Asp.net Core程序代码部署到Ubuntu(不含数据库)
    2019周笔记(3.11-3.16)
    利用StackExchange.Redis和Log4Net构建日志队列
    Windows环境下安装配置Mosquitto服务及入门操作介绍
    2019周笔记(2.25-3.01)(压缩数据库)
    2019周笔记(2.18-2.23)
    WinForm客户端限速下载(C#限速下载)
    2019周笔记(2.14-2.17)(聚集索引、非聚集索引)
    高并发场景下秒杀项目静态锁的使用疑问
    线性结构队列以及应用(上)
  • 原文地址:https://www.cnblogs.com/zhy-1992/p/6606141.html
Copyright © 2011-2022 走看看