WebSocket不能像TCP的Socket那样直连,需要通过服务端中转。
那么首先我们创建一个windows服务,开启后网页只要连接即可。
一、WebSocket服务端
using System;
using System.Collections.Generic;
using Fleck;
using log4net;
using Topshelf;
namespace com.CTT.WebSocketService
{
public class WebSocketHandler
{
readonly ILog log = LogManager.GetLogger("WebSocketService");
WebSocketServer server = new WebSocketServer(System.Configuration.ConfigurationManager.AppSettings["server_url"])
{
RestartAfterListenError = true //出错后进行重启
};
//记录所有连接的客户端
IDictionary<string, IWebSocketConnection> dictSockets = new Dictionary<string, IWebSocketConnection>();
public WebSocketHandler()
{
//开始监听
server.Start(socket =>
{
socket.OnOpen = () => //连接建立事件
{
//获取客户端网页的url
var clientUrl = socket.ConnectionInfo.ClientIpAddress ":" socket.ConnectionInfo.ClientPort;
if (!dictSockets.ContainsKey(clientUrl))
{
dictSockets.Add(clientUrl, socket);
log.Info("和客户端网页:" clientUrl " 建立WebSock连接");
}
};
socket.OnClose = () => //连接关闭事件
{
var clientUrl = socket.ConnectionInfo.ClientIpAddress ":" socket.ConnectionInfo.ClientPort;
//如果存在这个客户端,那么对这个socket进行移除
if (dictSockets.ContainsKey(clientUrl))
dictSockets.Remove(clientUrl);
log.Info("和客户端网页:" clientUrl " 断开WebSock连接");
};
socket.OnMessage = message => //接受客户端网页消息事件
{
var clientUrl = socket.ConnectionInfo.ClientIpAddress ":" socket.ConnectionInfo.ClientPort;
if (dictSockets != null && dictSockets.Count > 0)
{
foreach (var item in dictSockets.Values)
item.Send(message); //给所有连接的客户端广播
}
log.Info("收到" clientUrl "的消息,并广播消息:" message);
};
});
}
public void Start()
{
log.Info("启用服务");
}
public void Stop()
{
if (dictSockets != null && dictSockets.Count > 0)
{
foreach (var item in dictSockets.Values)
item.Close(); //关闭所有的连接
}
log.Info("关闭服务");
}
}
class Program
{
static void Main(string[] args)
{
//var logCfg = new FileInfo(AppDomain.CurrentDomain.BaseDirectory "log4net.config");
//XmlConfigurator.ConfigureAndWatch(logCfg);
var rc = HostFactory.Run(x => //1
{
x.Service<WebSocketHandler>(s => //2
{
s.ConstructUsing(name => new WebSocketHandler()); //3
s.WhenStarted(tc => tc.Start()); //4
s.WhenStopped(tc => tc.Stop()); //5
});
x.RunAsLocalSystem(); //6
x.SetDescription("先配置server_url,网页的websocket指向此地址,实现实时通讯"); //服务描述
x.SetDisplayName("WebSocket服务端"); //服务显示名称
x.SetServiceName("com.CTT.WebSocketService"); //服务名称
}); //10
var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode()); //11
Environment.ExitCode = exitCode;
}
}
}
注意:在app.config里配置服务端地址server_url:ws://192.168.0.211:8181
这里使用了Fleck框架,他会自动生成WebSocket的服务器,Fleck是开源的组件,开源地址是:https://github.com/statianzo/Fleck
生成Release版本,并生成服务
打开cmd,cd到文件所在目录,执行以下命令(注意:必须要管理员权限,不然安装不成功)
com.CTT.WebSocketService Install //安装
com.CTT.WebSocketService Start //启动
com.CTT.WebSocketService Stop //停止
com.CTT.WebSocketService UnInstall //卸载服务
二、网页客户端
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
.message{
width: 60%;
margin: 0 10px;
display: inline-block;
text-align: center;
height: 40px;
line-height: 40px;
font-size: 20px;
border-radius: 5px;
border: 1px solid #B3D33F;
}
.form{
width:100%;
position: fixed;
bottom: 300px;
left: 0;
}
.connect{
height: 40px;
vertical-align: top;
/* padding: 0; */
width: 80px;
font-size: 20px;
border-radius: 5px;
border: none;
background: #B3D33F;
color: #fff;
}
</style>
</head>
<body onload="connectWebSocket();">
<ul id="content"></ul>
<form class="form">
<input type="text" placeholder="请输入发送的消息" class="message" id="message"/>
<input type="button" value="发送" id="send" class="connect"/>
</form>
</body>
</html>
<script>
var ws=null;
var oUl=document.getElementById('content');
var oSend=document.getElementById('send');
var oInput=document.getElementById('message');
var connectWebSocket=function(){
ws=new WebSocket('ws://192.168.0.211:8181');
ws.onopen=function(){
oUl.innerHTML ="<li>客户端已连接</li>";
}
ws.onmessage=function(evt){
oUl.innerHTML ="<li>" evt.data "</li>";
}
ws.onclose=function(){
oUl.innerHTML ="<li>客户端已断开连接</li>";
};
ws.onerror=function(evt){
oUl.innerHTML ="<li>" evt.data "</li>";
};
}
oSend.onclick=function(){
if(ws){
ws.send(oInput.value);
}
}
</script>
打开网页,立即连接上了服务端。
尝试创建2个相同的网站客户端,在其中一个网站发送消息,另一个也能收到。