前端代码:
function SocketHelper(params) {
var options = $.extend({}, {
uri: "ws://" + window.location.host + "//socket/Connect",
Received: function (result) { },//接收事件
ReceiverId: "" //接收人
}, params);
var socket;//对象
var SenderId = "";//发送人
Connect = function () {
// this.uri = uri;
this.socket = new WebSocket(options.uri);
this.socket.onopen = function (e) { _self.Open(e) };
var _self = this;
this.socket.onmessage = function (e) { _self.Received(e); };
this.socket.onerror = function (e) { _self.Error(e); };
};
Send = function (ReceiverId, message) {
var sendData = { "SenderId": SenderId, "ReceiverId": ReceiverId, "MessageType": "text", "Content": message };
try {
this.socket.send(JSON.stringify(sendData));
} catch (e) {
this.Connect();
}
};
Open = function (e) {
this.Send("Service","连接");
console.log("socket opened", e);
};
Close = function (e) {
this.socket.close();
console.log("socket closed", e);
};
Received = function (e) {
var result = JSON.parse(e.data);
if (options.Received) {
options.Received(result);
}
if (result.SenderId == "Service" && result.Content == "open")
{
SenderId = result.ReceiverId;
}
console.log("Received: " + result.ReceiverId);
};
Error = function (e) {
console.log("Error: " + e.data);
}
return this;
}
后端实现
private static ConcurrentDictionary<string, WebSocket> _socketConnectUsers;
/// <summary>
/// 用于存储在线的websocket用户
/// </summary>
public static ConcurrentDictionary<string, WebSocket> SocketConnectUsers
{
get {
return _socketConnectUsers;
}
}
public const int BufferSize = 4096;
private string _sockSenderId = "";
WebSocket socket;
public WebSocketHelper(WebSocket socket)
{
this.socket = socket;
}
async Task EchoLoop()
{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await this.socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (_socketConnectUsers == null)
{
_socketConnectUsers = new ConcurrentDictionary<string, WebSocket>();
}
#region 创建websocket Id
if (string.IsNullOrWhiteSpace(ApplicationEnvironments.DefaultSession.UserName))
{
_sockSenderId = Guid.NewGuid().ToString();
}
else
{
_sockSenderId = ApplicationEnvironments.DefaultSession.UserName;
}
#endregion
if (!result.CloseStatus.HasValue)//第一次连接
{
_socketConnectUsers.TryAdd(_sockSenderId, socket);
await SendAsync(new WSMessageHelper {//连接成功时返回用户id
SenderId="Service",
ReceiverId= _sockSenderId,
MessageType="text",
Content="open"
}, WebSocketMessageType.Text, result.EndOfMessage);
}
while (!result.CloseStatus.HasValue)
{
string sendMsg= ReceiveString(buffer,result);
WSMessageHelper wSMessage = null;
if (!string.IsNullOrWhiteSpace(sendMsg))
{
wSMessage= JSONHelper.FromJson<WSMessageHelper>(sendMsg);
}
if (wSMessage != null&&!string.IsNullOrWhiteSpace(wSMessage.ReceiverId)&& !wSMessage.ReceiverId.ToLower().Equals("service"))
{
if (!await SendAsync(wSMessage, WebSocketMessageType.Text, true))//false表示发送失败
{
await SendAsync(new WSMessageHelper //,失败时回发用户消息
{
SenderId = "Service",
ReceiverId = _sockSenderId,
MessageType = "text",
Content = "消息发送不成功,用户已下线"
}, WebSocketMessageType.Text, result.EndOfMessage);
}
}
result = await this.socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
_socketConnectUsers.TryRemove(_sockSenderId,out socket);
await this.socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="message">消息对象</param>
/// <param name="messageType">消息类型</param>
/// <param name="endOfMessage">是否结束消息</param>
/// <returns></returns>
public async Task<bool> SendAsync(WSMessageHelper message, WebSocketMessageType messageType, bool endOfMessage)
{
var buffer1 = FileHelper.StringToByte("utf-8", JSONHelper.ToJson(message));
var outgoing = new ArraySegment<byte>(buffer1, 0, buffer1.Length);
WebSocket socket = null;
if (_socketConnectUsers.TryGetValue(message.ReceiverId, out socket))
{
await socket.SendAsync(outgoing, messageType, endOfMessage, CancellationToken.None);
return true;
}
return false;
}
private string ReceiveString(ArraySegment<byte> buffer,WebSocketReceiveResult result)
{
using (var ms = new MemoryStream())
{
do
{
ms.Write(buffer.Array, buffer.Offset, result.Count);
}
while (!result.EndOfMessage);
ms.Seek(0, SeekOrigin.Begin);
if (result.MessageType != WebSocketMessageType.Text)
{
return null;
}
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
static async Task Acceptor(HttpContext hc, Func<Task> n)
{
if (!hc.WebSockets.IsWebSocketRequest)
return;
var socket = await hc.WebSockets.AcceptWebSocketAsync();
var h = new WebSocketHelper(socket);
await h.EchoLoop();
}
/// <summary>
/// 路由绑定处理
/// </summary>
/// <param name="app"></param>
public static void Map(IApplicationBuilder app)
{
app.UseWebSockets();
app.Use(WebSocketHelper.Acceptor);
}
消息对象类
public class WSMessageHelper
{
/// <summary>
/// 发送者Id
/// </summary>
public string SenderId { get; set; }
/// <summary>
/// 接受者id
/// </summary>
public string ReceiverId { get; set; }
/// <summary>
/// 消息类型
/// </summary>
public string MessageType { get; set; }
public object Content { get; set; }
}
在Startup类中增加以下代码
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Map("/socket/Connect", WebSocketHelper.Map);
}