(精华)2020年8月20日 C#基础知识点 Socket的使用
(精华)2020年8月20日 C#基础知识点 Socket的使用
一:Socket的基本使用
tcp使用
服务端
public static void Proccess()
{<!-- -->
int port = 2018;
string host = "127.0.0.1";
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sSocket.Bind(ipe);
sSocket.Listen(0);
Console.WriteLine("监听已经打开,请等待");
//收到消息 接受一个socket链接
Socket serverSocket = sSocket.Accept();
Console.WriteLine("连接已经建立。。。");
while (true)
{<!-- -->
string recStr = "";
byte[] recByte = new byte[4096];
int bytes = serverSocket.Receive(recByte, recByte.Length, 0);
recStr += Encoding.ASCII.GetString(recByte, 0, bytes);
Console.WriteLine("服务器端获得信息:{0}", recStr);
if (recStr.Equals("stop"))
{<!-- -->
serverSocket.Close();//关闭该socket对象
Console.WriteLine("关闭链接。。。。");
break;
}
//回发消息
Console.WriteLine("请输入回发消息。。。。");
string sendStr = Console.ReadLine(); //"send to client :hello world";
byte[] sendByte = Encoding.ASCII.GetBytes(sendStr);
serverSocket.Send(sendByte, sendByte.Length, 0);
}
sSocket.Close();//关闭server监听
}
客户端
static void Main(string[] args)
{<!-- -->
try
{<!-- -->
Console.WriteLine("启动一个Socket客户端链接");
int port = 2018;
string host = "127.0.0.1";//服务器端ip地址
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(ipe); //开启链接以后,是长链接;
while (true)
{<!-- -->
Console.WriteLine("请输入发送到服务器的信息:");
string sendStr = Console.ReadLine();
if (sendStr == "exit")
break;
byte[] sendBytes = Encoding.ASCII.GetBytes(sendStr);
clientSocket.Send(sendBytes);
//receive message
string recStr = "";
byte[] recBytes = new byte[4096];
//监控传递过来的消息;
int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0);
recStr += Encoding.ASCII.GetString(recBytes, 0, bytes);
Console.WriteLine($"服务器返回:{recStr}");
}
clientSocket.Close();
}
catch (Exception ex)
{<!-- -->
Console.WriteLine(ex.Message);
}
Console.Read();
}
UDP的使用
服务端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace UDP_Server
{<!-- -->
class Program
{<!-- -->
static Socket server;
static void Main(string[] args)
{<!-- -->
server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
server.Bind(new IPEndPoint(IPAddress.Parse("169.254.202.67"), 6001));//绑定端口号和IP
Console.WriteLine("服务端已经开启");
Thread t = new Thread(ReciveMsg);//开启接收消息线程
t.Start();
Thread t2 = new Thread(sendMsg);//开启发送消息线程
t2.Start();
}
/// <summary>
/// 向特定ip的主机的端口发送数据报
/// </summary>
static void sendMsg()
{<!-- -->
EndPoint point = new IPEndPoint(IPAddress.Parse("169.254.202.67"), 6000);
while (true)
{<!-- -->
string msg = Console.ReadLine();
server.SendTo(Encoding.UTF8.GetBytes(msg), point);
}
}
/// <summary>
/// 接收发送给本机ip对应端口号的数据报
/// </summary>
static void ReciveMsg()
{<!-- -->
while (true)
{<!-- -->
EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号
byte[] buffer = new byte[1024];
int length = server.ReceiveFrom(buffer, ref point);//接收数据报
string message = Encoding.UTF8.GetString(buffer,0,length);
Console.WriteLine(point.ToString()+ message);
}
}
}
}
客户端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace UDP_client
{<!-- -->
class Program
{<!-- -->
static Socket client;
static void Main(string[] args)
{<!-- -->
client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.Bind(new IPEndPoint(IPAddress.Parse("169.254.202.67"), 6000));
Thread t = new Thread(sendMsg);
t.Start();
Thread t2 = new Thread(ReciveMsg);
t2.Start();
Console.WriteLine("客户端已经开启");
}
/// <summary>
/// 向特定ip的主机的端口发送数据报
/// </summary>
static void sendMsg()
{<!-- -->
EndPoint point = new IPEndPoint(IPAddress.Parse("169.254.202.67"), 6001);
while(true){<!-- -->
string msg = Console.ReadLine();
client.SendTo(Encoding.UTF8.GetBytes(msg), point);
}
}
/// <summary>
/// 接收发送给本机ip对应端口号的数据报
/// </summary>
static void ReciveMsg()
{<!-- -->
while (true)
{<!-- -->
EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号
byte[] buffer = new byte[1024];
int length = client.ReceiveFrom(buffer, ref point);//接收数据报
string message = Encoding.UTF8.GetString(buffer, 0, length);
Console.WriteLine(point.ToString() + message);
}
}
}
}
二:SuperSocket的使用
首先安装:SuperSocket.Engine
SuperSoket的三大对象:
- Session: 每一个用户连接就是一个Session1. AppServer: Socket服务器实例1. Commands: 客户端向服务器发送消息的命令集合 首先在配置文件加入如下配置
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="superSocket" type="SuperSocket.SocketEngine.Configuration.SocketServiceConfig, SuperSocket.SocketEngine"/>
</configSections>
<superSocket>
<servers>
<server name="ChatSocket" textEncoding="gb2312"
serverType="XT.SocketService.AppServer.ChatServer,XT.SocketService"
ip="Any" port="2020"
maxConnectionNumber="100">
</server>
<!-- 可以配置多个Server-->
</servers>
</superSocket>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
创建个ChatServer服务
[AuthorisizeFilter]
public class ChatServer:AppServer<ChatSession>
{<!-- -->
protected override bool Setup(IRootConfig rootConfig, IServerConfig config)
{<!-- -->
Console.WriteLine("准备读取配置文件。。。。");
return base.Setup(rootConfig, config);
}
protected override void OnStarted()
{<!-- -->
Console.WriteLine("Chat服务启动。。。");
base.OnStarted();
}
protected override void OnStopped()
{<!-- -->
Console.WriteLine("Chat服务停止。。。");
base.OnStopped();
}
/// <summary>
/// 新的连接
/// </summary>
/// <param name="session"></param>
protected override void OnNewSessionConnected(ChatSession session)
{<!-- -->
Console.WriteLine($"Chat服务新加入的连接:{session.LocalEndPoint.Address.ToString()}");
base.OnNewSessionConnected(session);
}
}
class AuthorisizeFilterAttribute : CommandFilterAttribute
{<!-- -->
public override void OnCommandExecuting(CommandExecutingContext commandContext)
{<!-- -->
ChatSession session = (ChatSession)commandContext.Session;
string command = commandContext.CurrentCommand.Name;
if (!session.IsLogin)
{<!-- -->
if (!command.Equals("Check"))
{<!-- -->
session.Send("请先登录以后,再操作。。。");
commandContext.Cancel = true;//不再继续往后走;
}
else
{<!-- -->
///....
}
}
else if (!session.IsOnLine)
{<!-- -->
session.LastHbTime = DateTime.Now;
}
}
public override void OnCommandExecuted(CommandExecutingContext commandContext)
{<!-- -->
//throw new NotImplementedException();
}
}
创建个Session服务
/// <summary>
/// 表示用户连接
/// </summary>
//[AuthorisizeFilter]
public class ChatSession : AppSession<ChatSession>
{<!-- -->
public string Id {<!-- --> get; set; }
public string PassWord {<!-- --> get; set; }
public bool IsLogin {<!-- --> get; set; }
public DateTime LoginTime {<!-- --> get; set; }
public DateTime LastHbTime {<!-- --> get; set; }
public bool IsOnline
{<!-- -->
get
{<!-- -->
return this.LastHbTime.AddSeconds(10) > DateTime.Now;
}
}
/// <summary>
/// 消息发送
/// </summary>
/// <param name="message"></param>
public override void Send(string message)
{<!-- -->
Console.WriteLine($"准备发送给{this.Id}:{message}");
base.Send(message.Format());
}
protected override void OnSessionStarted()
{<!-- -->
this.Send("Welcome to SuperSocket Chat Server");
}
protected override void OnInit()
{<!-- -->
this.Charset = Encoding.GetEncoding("gb2312");
base.OnInit();
}
protected override void HandleUnknownRequest(StringRequestInfo requestInfo)
{<!-- -->
Console.WriteLine("收到命令:" + requestInfo.Key.ToString());
this.Send("不知道如何处理 " + requestInfo.Key.ToString() + " 命令");
}
/// <summary>
/// 异常捕捉
/// </summary>
/// <param name="e"></param>
protected override void HandleException(Exception e)
{<!-- -->
this.Send($"\n\r异常信息:{ e.Message}");
//base.HandleException(e);
}
/// <summary>
/// 连接关闭
/// </summary>
/// <param name="reason"></param>
protected override void OnSessionClosed(CloseReason reason)
{<!-- -->
Console.WriteLine("链接已关闭。。。");
base.OnSessionClosed(reason);
}
}
Commands代码如下 : 客户端发送消息命令 Check 1 123456
Check 代表类名 ,1代表session.id(会话ID),1代表session.PassWord (会话密码)
public class Check : CommandBase<ChatSession, StringRequestInfo>
{<!-- -->
public override void ExecuteCommand(ChatSession session, StringRequestInfo requestInfo)
{<!-- -->
if (requestInfo.Parameters != null && requestInfo.Parameters.Length == 2)
{<!-- -->
ChatSession oldSession = session.AppServer.GetAllSessions().FirstOrDefault(a => requestInfo.Parameters[0].Equals(a.Id));
if (oldSession != null) // 说过之前有用户用这个Id 登录过
{<!-- -->
oldSession.Send("您的账号已经在他处登录,您已经被踢下线了");
oldSession.Close();
}
#region 这里就可以连接数据库进行数据验证做登录
///---------------------
#endregion
session.Id = requestInfo.Parameters[0];
session.PassWord = requestInfo.Parameters[1];
session.IsLogin = true;
session.LoginTime = DateTime.Now;
session.Send("登录成功");
{<!-- --> // 获取当前登录用户的离线消息
ChatDataManager.SendLogin(session.Id, c =>
{<!-- -->
session.Send($"{c.FromId} 给你发送消息:{c.Message} {c.Id}");
});
}
}
else
{<!-- -->
session.Send("参数错误");
}
}
}
离线消息存储的相关类
public class ChatDataManager
{<!-- -->
/// <summary>
/// key是用户id
/// List 这个用户的全部消息
/// </summary>
private static Dictionary<string, List<ChatModel>> Dictionary = new Dictionary<string, List<ChatModel>>();
public static void Add(string userId, ChatModel model)
{<!-- -->
if (Dictionary.ContainsKey(userId))
{<!-- -->
Dictionary[userId].Add(model);
}
else
{<!-- -->
Dictionary[userId] = new List<ChatModel>() {<!-- --> model };
}
}
public static void Remove(string userId, string modelId)
{<!-- -->
if (Dictionary.ContainsKey(userId))
{<!-- -->
Dictionary[userId] = Dictionary[userId].Where(m => m.Id != modelId).ToList();
}
}
public static void SendLogin(string userId, Action<ChatModel> action)
{<!-- -->
if (Dictionary.ContainsKey(userId))
{<!-- -->
foreach (var item in Dictionary[userId])
{<!-- -->
action.Invoke(item);
item.State = 1;
}
}
}
}
/// <summary>
/// 一条消息的记录
/// </summary>
public class ChatModel
{<!-- -->
/// <summary>
/// 每条分配个唯一Id
/// </summary>
public string Id {<!-- --> get; set; }
/// <summary>
/// 来源编号
/// </summary>
public string FromId {<!-- --> get; set; }
/// <summary>
/// 目标编号
/// </summary>
public string ToId {<!-- --> get; set; }
/// <summary>
/// 消息内容
/// </summary>
public string Message {<!-- --> get; set; }
/// <summary>
/// 消息时间
/// </summary>
public DateTime CreateTime {<!-- --> get; set; }
/// <summary>
/// 消息状态 0未发送 1已发送待确认 2确认收到
/// </summary>
public int State {<!-- --> get; set; }
}
基本使用获取离线消息
public class Chat : CommandBase<ChatSession, StringRequestInfo>
{<!-- -->
public override void ExecuteCommand(ChatSession session, StringRequestInfo requestInfo)
{<!-- -->
// 还是传递两个参数 1、 要发给谁 ToId 2、消息内容
if (requestInfo.Parameters != null && requestInfo.Parameters.Length == 2)
{<!-- -->
string toId = requestInfo.Parameters[0];
string message = requestInfo.Parameters[1];
ChatSession toSession = session.AppServer.GetAllSessions().FirstOrDefault(a => toId.Equals(a.Id));
string modelId = Guid.NewGuid().ToString();
if (toSession != null) // 说过之前有用户用这个Id 登录过
{<!-- -->
toSession.Send($"{session.Id} 给你发消息:{message} {modelId}");
ChatDataManager.Add(toId, new ChatModel()
{<!-- -->
FromId = session.Id,
ToId = toId,
Message = message,
Id = modelId,
State = 1,// 待确认
CreateTime = DateTime.Now
});
}
else
{<!-- -->
ChatDataManager.Add(toId, new ChatModel()
{<!-- -->
FromId = session.Id,
ToId = toId,
Message = message,
Id = modelId,
State = 0,// 未发送
CreateTime = DateTime.Now
});
session.Send("消息未发送成功");
}
}
else
{<!-- -->
session.Send("参数错误");
}
}
}
public class Confirm : CommandBase<ChatSession, StringRequestInfo>
{<!-- -->
public override void ExecuteCommand(ChatSession session, StringRequestInfo requestInfo)
{<!-- -->
if (requestInfo.Parameters != null && requestInfo.Parameters.Length == 1)
{<!-- -->
string modelId = requestInfo.Parameters[0];
Console.WriteLine($"用户{session.Id} 已确认,收到消息{modelId}");
ChatDataManager.Remove(session.Id, modelId);
}
else
{<!-- -->
session.Send("参数错误");
}
}
}
心跳检测:主要就是定时发送消息,没接到消息就发起重连
public class HB : CommandBase<ChatSession, StringRequestInfo>
{<!-- -->
public override void ExecuteCommand(ChatSession session, StringRequestInfo requestInfo)
{<!-- -->
if (requestInfo.Parameters != null && requestInfo.Parameters.Length == 1)
{<!-- -->
if ("R".Equals(requestInfo.Parameters[0]))
{<!-- -->
session.LastHbTime = DateTime.Now;
session.Send("R");
}
else
{<!-- -->
session.Send("参数错误");
}
}
else
{<!-- -->
session.Send("参数错误");
}
}
}
使用
public class SuperSocketMain
{<!-- -->
//1 SuperSocket引入和使用
//2 聊天室之用户登录&唯一登陆
//3 在线发消息&确认收到&离线消息
//4 心跳检测机制&断线重连
//5 CommandFilterAttribute的AOP机制
public static void Init()
{<!-- -->
//可以通过配置文件来配置以后,运行SuperSocket服务;
//需要读取配置文件启动服务;
try
{<!-- -->
//支持通过配置文件读取对服务启动
IBootstrap bootstrap = BootstrapFactory.CreateBootstrap();
if (!bootstrap.Initialize())
{<!-- -->
Console.WriteLine("初始化失败");
Console.ReadKey();
return;
}
Console.WriteLine("准备启动服务");
var result = bootstrap.Start();
foreach (var server in bootstrap.AppServers)
{<!-- -->
if (server.State == ServerState.Running)
{<!-- -->
Console.WriteLine($"{server.Name}运行中");
}
else
{<!-- -->
Console.WriteLine($"{server.Name}启动失败");
}
}
}
catch (Exception ex)
{<!-- -->
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
二:WebSocket的使用
<form id="form1" runat="server">
<div>
<input id="userName" type="text" />
<input id="conn" type="button" value="连接" />
<input id="close" type="button" value="关闭" />
<span id="tips"></span>
<input id="content" type="text" />
<input id="send" type="button" value="发送" />
</div>
<div id="view">
<ul></ul>
</div>
</form>
<script src="~/Scripts/jquery-3.3.1.js"></script>
<script type="text/javascript">
$(function () {<!-- -->
// http:// https://
// ws 开头, 也可以wss开头
var socket;
var url = "ws://localhost:57211/Home/MyWebSocket";
function connect() {<!-- -->
var socketurl = url + "?name=" + $("#userName").val();
socket = new WebSocket(socketurl);// 就是用来建立即时通信同道 Socket长链接
// 会有一个握手的过程
// 去链接的后台方法可以是MVC控制器里的方法,也可以是WebApi,还可以支持一般处理程序,也可以支持aspx
//链接打开的时候触发
socket.onopen = function () {<!-- -->
$("#tips").text("链接已打开");
// 定时发送一个消息给服务器发送心跳包 服务器接收到心跳包以后马上就再回复一个消息给客户端
// 如果我发现十秒钟或者在间隔时间内 接受不到服务器回复的心跳消息 我就认为连接掉线
// 这时候就需要断线 connect();
}
// 接受服务器发送过来的消息
socket.onmessage = function (evt) {<!-- -->
$("#view ul").append("<li>" + evt.data + "</li>");
}
// 异常的时候触发方法
socket.onerror = function (evt) {<!-- -->
$("#tips").text(JSON.stringify(evt));
}
// 链接关闭的时候触发
socket.onclose = function () {<!-- -->
$("#tips").text("连接关闭了");
}
}
// 点击"连接"按钮
$("#conn").on("click", function () {<!-- -->
connect();
})
//点击“关闭”按钮
$("#close").on("click", function () {<!-- -->
socket.close();
})
//点击“发送”按钮
$("#send").on("click", function () {<!-- -->
if (socket.readyState == WebSocket.OPEN) {<!-- -->
socket.send($("#content").val());
}
else {<!-- -->
alert("链接已经断开");
}
})
})
</script>
后端处理
public class HomeController : Controller
{<!-- -->
public ActionResult WebSocket()
{<!-- -->
return View();
}
private string UserName = string.Empty;
/// <summary>
/// WebSocket建立链接的方法
/// </summary>
/// <param name="name"></param>
public void MyWebSocket(string name)
{<!-- -->
if (HttpContext.IsWebSocketRequest)
{<!-- -->
this.UserName = name;
HttpContext.AcceptWebSocketRequest(ProcessChat);
}
else
{<!-- -->
HttpContext.Response.Write("我不处理");
}
}
public async Task ProcessChat(AspNetWebSocketContext socketContext)
{<!-- -->
// SuperSocket:Session
// 表示客户端发起请求的一个链接
System.Net.WebSockets.WebSocket socket = socketContext.WebSocket;
CancellationToken token = new CancellationToken();
string socketGuid = Guid.NewGuid().ToString();
OldChatManager.AddUser(socketGuid, UserName, socket, token);
await OldChatManager.SengdMessage(token, UserName, "进入聊天室");
while (socket.State == WebSocketState.Open)
{<!-- -->
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, token);
string userMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count); // 来自于客户端发送过来的消息内容
if (result.MessageType == WebSocketMessageType.Close)
{<!-- -->
OldChatManager.RemoveUser(socketGuid);
await OldChatManager.SengdMessage(token, UserName, "离开聊天室");
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, token);
}
else
{<!-- -->
await OldChatManager.SengdMessage(token, UserName, userMessage);
}
}
}
}
相关类
public class SocketModel
{<!-- -->
/// <summary>
/// 链接的唯一ID
/// </summary>
public string SocketGuid {<!-- --> get; set; }
/// <summary>
/// 用户名称
/// </summary>
public string UserName {<!-- --> get; set; }
/// <summary>
/// 每一个用户链接进来以后 对应的这一个Socket实例
/// </summary>
public WebSocket Socket {<!-- --> get; set; }
}
public class OldChatManager
{<!-- -->
///一个群就应该有固定的的人数;
/// <summary>
/// 默认某一个群组里面有这么一些人
/// 1.默认这个群里就有四个人;
/// </summary>
public static List<SocketModel> socketlist = new List<SocketModel>() {<!-- -->
new SocketModel(){<!-- --> SocketGuid=string.Empty,UserName="User1",Socket=null },
new SocketModel(){<!-- --> SocketGuid=string.Empty,UserName="User2",Socket=null },
new SocketModel(){<!-- --> SocketGuid=string.Empty,UserName="User3",Socket=null },
new SocketModel(){<!-- --> SocketGuid=string.Empty,UserName="User4",Socket=null }
};
// string: 要发谁 ArraySegment<byte>:要发送的消息
public static Dictionary<string, List<ArraySegment<byte>>> chatList = new Dictionary<string, List<ArraySegment<byte>>>();
public static void AddUser(string socketGuid, string userName, WebSocket socket, CancellationToken token)
{<!-- -->
socketlist.ForEach(item =>
{<!-- -->
if (userName == item.UserName)
{<!-- -->
item.Socket = socket;
item.SocketGuid = socketGuid;
}
});
if (chatList.ContainsKey(userName) && chatList[userName].Count > 0)
{<!-- -->
foreach (var item in chatList[userName])
{<!-- -->
socket.SendAsync(item, WebSocketMessageType.Text, true, token);
}
}
}
public static void RemoveUser(string socketGuid)
{<!-- -->
socketlist.ForEach(item =>
{<!-- -->
if (socketGuid == item.SocketGuid)
{<!-- -->
item.Socket = null;
item.SocketGuid = null;
}
});
}
/// <summary>
/// 群发消息 包括离线消息
/// </summary>
/// <param name="token"></param>
/// <param name="userName"></param>
/// <param name="content"></param>
/// <returns></returns>
public static async Task SengdMessage(CancellationToken token, string userName, string content)
{<!-- -->
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes($"{DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss:fff")}{userName}:{content}"));
foreach (var socketInfo in socketlist)
{<!-- -->
if (socketInfo.Socket == null)
{<!-- -->
if (chatList.ContainsKey(socketInfo.UserName))
{<!-- -->
chatList[socketInfo.UserName].Add(buffer);
}
else
{<!-- -->
chatList.Add(socketInfo.UserName, new List<ArraySegment<byte>>() {<!-- --> buffer });
}
}
else
{<!-- -->
await socketInfo.Socket.SendAsync(buffer, WebSocketMessageType.Text, true, token);
}
}
}
public static async Task Say(CancellationToken token, string userName, string content)
{<!-- -->
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes($"{DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss:fff")}{userName}:{content}"));
foreach (var socketInfo in socketlist)
{<!-- -->
if (socketInfo.Socket!=null)
{<!-- -->
await socketInfo.Socket.SendAsync(buffer, WebSocketMessageType.Text, true, token);
}
}
}
}
public class ChatManager
{<!-- -->
/// <summary>
/// 每一个Socket对应一个客户端和服务器的连接(也可理解成一个用户)
///
/// </summary>
public static List<SocketModel> socketlist = new List<SocketModel>();
//SocketModel 建议大家保存在NoSql Redis MongoDb;
public static void SendOne(string messge, CancellationToken cancellationToken)
{<!-- -->
// user1;你好
string[] messageArray = messge.Split(':'); //toUser:Message;
string toUser = messageArray[0];
string toMessage = messageArray[1];
var socketModel = socketlist.FirstOrDefault(a => toUser.Equals(a.UserName));
if (socketModel != null)
{<!-- -->
WebSocket toSocket = socketModel.Socket;
ArraySegment<byte> buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(toMessage));
toSocket.SendAsync(buffer, WebSocketMessageType.Text, true, cancellationToken);
}
}
/// <summary>
/// 添加一个用户(包含了这个用户对应的Socket)
/// </summary>
/// <param name="socketGuid"></param>
/// <param name="userName"></param>
/// <param name="socket"></param>
public static void AddUser(string socketGuid, string userName, WebSocket socket)
{<!-- -->
socketlist.Add(new SocketModel()
{<!-- -->
SocketGuid = socketGuid,
UserName = userName,
Socket = socket
});
}
/// <summary>
/// 删除已经连接的用户
/// </summary>
/// <param name="socketGuid"></param>
public static void RemoveUser(string socketGuid)
{<!-- -->
socketlist = socketlist.Where(a => a.SocketGuid != socketGuid).ToList();
}
/// <summary>
/// 群发消息
/// </summary>
/// <param name="token"></param>
/// <param name="userName"></param>
/// <param name="content"></param>
/// <returns></returns>
public static async Task SengdMessage(CancellationToken token, string userName, string content)
{<!-- -->
///WebSocket 消息发送的格式 消息内容的长度
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes($"{DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss:fff")}{userName}:{content}"));
///给每一个Socket (用户) 发送消息 (类似于一个广播的形式)
foreach (var socketInfo in socketlist)
{<!-- -->
await socketInfo.Socket.SendAsync(buffer, WebSocketMessageType.Text, true, token);
}
}
}