Demo - 基于.NET+Socket实现多人聊天室
(一)Demo涉及技术
开发语言:C#
GUI:WPF(MVVM)
框架:Prism(不重要)
核心包:System.Net.Sockets
(二)功能演示
Demo采用C#\WPF\MVVM,包含一个服务端应用、一个客户端应用。
(三)核心代码
服务端代码
private void StartServer()
{
if (ServerSocket != null) return;
// 1 创建服务端Socket
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 2 Bind
IPAddress iPAddress = IPAddress.Parse(ServerIp);
IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, ServerPort);
ServerSocket.Bind(iPEndPoint);
// 3 Listen
ServerSocket.Listen(MaxConnect);
State = "已启动";
RemindMessage(ServerSocket.LocalEndPoint?.ToString() ?? "", EndPointType.Local, "服务已启动!");
// 4 Accept
Task.Run(() => Accept(ServerSocket));
}
/// <summary>
/// 等待客户端连接服务端
/// </summary>
/// <param name="serverSocket"></param>
private void Accept(Socket serverSocket)
{
while (true)
{
// Accept方法会造成此线程的阻塞,等待客户端的连接
Socket clientSocket = serverSocket.Accept();
RemindClinetOnline(clientSocket);
// Receive
Task.Run(() => Receive(clientSocket));
}
}
/// <summary>
/// 接收客户端发送消息
/// </summary>
/// <param name="clinetSocket"></param>
private void Receive(Socket clinetSocket)
{
byte[] data = new byte[1024 * 1024];
while (clinetSocket.Connected)
{
//读取客户端发送过来的数据
int readLeng = clinetSocket.Receive(data, 0, data.Length, SocketFlags.None);
//客户端断开连接
if (readLeng == 0)
{
RemindClinetOffline(clinetSocket);
break;
}
string content = Encoding.UTF8.GetString(data, 0, readLeng);
RemindMessage(clinetSocket.RemoteEndPoint?.ToString() ?? "", EndPointType.Remote, content);
// 转发到各个连接的客户端
var contentByte = Encoding.UTF8.GetBytes(content);
foreach (var clientSocket in ConnectedSockets.Except(new List<Socket>() { clinetSocket }))
{
clientSocket.Send(contentByte);
}
}
}
客户端代码
private void ConnectServer()
{
if (ClientSocket != null) return;
// 1 创建服务端Socket
ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 2 Connect
IPAddress iPAddress = IPAddress.Parse(ServerIp);
IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, ServerPort);
ClientSocket.Connect(iPEndPoint);
//RemindClinetOnline(ClientSocket);
Application.Current.Dispatcher.Invoke(() => { State = "已连接"; });
RemindMessage(clientSocket?.LocalEndPoint?.ToString() ?? "", EndPointType.Local, "启动连接");
// 4 Accept
Task.Run(() => Receive(ClientSocket));
}
private void DisconnectServer()
{
if (ClientSocket == null) return;
RemindMessage(ClientSocket.LocalEndPoint?.ToString() ?? "", EndPointType.Local, "断开连接");
Application.Current.Dispatcher.Invoke(() => { State = "未连接"; });
// 停止会话
ClientSocket.Shutdown(SocketShutdown.Both);
// 关闭连接
ClientSocket.Close();
ClientSocket = null;
}
private void SendMessage()
{
if (ClientSocket == null || string.IsNullOrEmpty(InputMessage)) return;
// 发送到连接到客户端
var sendBytes = Encoding.UTF8.GetBytes(InputMessage);
ClientSocket.Send(sendBytes);
RemindMessage(ClientSocket?.LocalEndPoint?.ToString() ?? "", EndPointType.Local, InputMessage);
Application.Current.Dispatcher.Invoke(() => { InputMessage = ""; });
}
/// <summary>
/// 接收客户端发送消息
/// </summary>
/// <param name="clientSocket"></param>
private void Receive(Socket clientSocket)
{
byte[] data = new byte[1024 * 1024];
while (true)
{
//读取客户端发送过来的数据
int readLeng = ClientSocket.Receive(data, 0, data.Length, SocketFlags.None);
//客户端断开连接,在客户端关闭命令发出后,会再接收到一次服务端发来的信息
if (readLeng == 0) break;
string content = Encoding.UTF8.GetString(data, 0, readLeng);
RemindMessage(clientSocket?.RemoteEndPoint?.ToString() ?? "", EndPointType.Remote, content);
}
}
(四).NET/Socket中服务端和服务端的工作过程
(五)项目地址
分类:
DotNet
, DotNet / WPF/MVVM
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律