1
1
NanoTurtle的小窝

基于UWP(NET Native)的多线程聊天室

发布于:Mar 22, 2025

嗨嗨嗨我又来了!

https://music.163.com/outchain/player?type=2&id=509626&auto=0&height=66

这几天我在编写WinUI3和UWP。因为我的小米4搭载了先进的Windows Phone10。接下来,我将展示一个多线程聊天室的代码并分享软件包(.7z)。
我是参考了一位CSDN大牛的文章:https://blog.csdn.net/weixin_42582160/article/details/122262483
并且使用了一点科技的力量(DeepSeek)做的。
截图

以下是主要代码:

xaml

csharp

<Pagex:Class="SimpleChat.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="using:SimpleChat"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"><Grid><Grid.ColumnDefinitions><ColumnDefinition Width="2*"/><ColumnDefinition Width="1*"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><!-- 聊天显示区域 --><ScrollViewer Grid.Column="0" Grid.Row="0" VerticalScrollBarVisibility="Auto"><TextBox x:Name="ChatEdit" IsReadOnly="True" AcceptsReturn="True" TextWrapping="Wrap"/></ScrollViewer><!-- 输入框 --><TextBox x:Name="InputLine" Grid.Column="0" Grid.Row="1" PlaceholderText="在此输入消息..."/><!-- 发送按钮 --><Button x:Name="SendBtn" Grid.Column="1" Grid.Row="1" Content="发送" Click="SendBtn_Click"/><!-- 配置面板 --><StackPanel Grid.Column="1" Grid.Row="0" Margin="10"><TextBlock Text="服务器 IP"/><TextBox x:Name="IpEdit" PlaceholderText="输入 IP 地址"/><Button x:Name="HostIpBtn" Content="获取本机 IP" Click="HostIpBtn_Click"/><TextBlock Text="服务器端口"/><TextBox x:Name="PortEdit" PlaceholderText="输入端口"/><TextBlock Text="昵称"/><TextBox x:Name="HostEdit" PlaceholderText="输入昵称"/><RadioButton x:Name="ServerRbtn" Content="服务器" Checked="ServerRbtn_Checked"/><RadioButton x:Name="ClientRbtn" Content="客户端" Checked="ClientRbtn_Checked"/><Button x:Name="ConnectBtn" Content="连接服务器" Click="ConnectBtn_Click"/><Button x:Name="BuildServerBtn" Content="创建服务器" Click="BuildServerBtn_Click"/><Button x:Name="QuitBtn" Content="退出" Click="QuitBtn_Click"/></StackPanel></Grid></Page>

666这个代码框眼都不演了。

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.ViewManagement;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

namespace SimpleChat
{
public sealed partial class MainPage : Page
{
private StreamSocket _socket; // 服务器或客户端 StreamSocket
private bool _isServer = true; // 是否为服务器模式
private bool _isRunning = false; // 服务器是否正在运行
private List <StreamSocket> _clientSockets = new List &lt;StreamSocket>(); // 客户端列表

public MainPage()
{
this.InitializeComponent();

// 设置窗口标题
var view = ApplicationView.GetForCurrentView();
view.Title = "SimpleChat";
}

// 发送消息按钮点击事件
private void SendBtn_Click(object sender, RoutedEventArgs e)
{
string message = InputLine.Text;
if (!string.IsNullOrEmpty(message))
{
string hostName = HostEdit.Text.Trim();
if (string.IsNullOrEmpty(hostName))
{
hostName = "Anonymous"; // 默认昵称
}

string fullMessage = $"{hostName}: {message}";
InputLine.Text = string.Empty; // 清空输入框

if (_isServer)
{
// 如果是服务器,在本地显示 "You: sth"
ChatEdit.Text += $"{Environment.NewLine}You: {message}";

// 广播消息给所有客户端(不包括自己)
BroadcastMessage(fullMessage);
}
else
{
// 如果是客户端,在本地显示 "You: sth"
ChatEdit.Text += $"{Environment.NewLine}You: {message}";

// 发送消息到服务器
SendMessageToServer(fullMessage);
}
}
}

// 获取本机 IP 按钮点击事件
private void HostIpBtn_Click(object sender, RoutedEventArgs e)
{
var hostNames = Windows.Networking.Connectivity.NetworkInformation.GetHostNames();
foreach (var hostName in hostNames)
{
if (hostName.Type == Windows.Networking.HostNameType.Ipv4)
{
IpEdit.Text = hostName.ToString();
break;
}
}
}

// 服务器模式单选按钮点击事件
private void ServerRbtn_Checked(object sender, RoutedEventArgs e)
{
_isServer = true;
ConnectBtn.IsEnabled = false;
BuildServerBtn.IsEnabled = true;
}

// 客户端模式单选按钮点击事件
private void ClientRbtn_Checked(object sender, RoutedEventArgs e)
{
_isServer = false;
ConnectBtn.IsEnabled = true;
BuildServerBtn.IsEnabled = false;
}

// 连接服务器按钮点击事件
private async void ConnectBtn_Click(object sender, RoutedEventArgs e)
{
if (!_isServer)
{
string ip = IpEdit.Text.Trim();
if (string.IsNullOrEmpty(ip))
{
ChatEdit.Text += $"{Environment.NewLine}IP address cannot be empty!";
return;
}

if (!int.TryParse(PortEdit.Text, out int port))
{
ChatEdit.Text += $"{Environment.NewLine}Invalid port number!";
return;
}

await ConnectToServerAsync(ip, port);
}
}

// 创建服务器按钮点击事件
private async void BuildServerBtn_Click(object sender, RoutedEventArgs e)
{
if (_isServer)
{
string ip = IpEdit.Text.Trim();
if (string.IsNullOrEmpty(ip))
{
ChatEdit.Text += $"{Environment.NewLine}IP address cannot be empty!";
return;
}

if (!int.TryParse(PortEdit.Text, out int port))
{
ChatEdit.Text += $"{Environment.NewLine}Invalid port number!";
return;
}

await StartServerAsync(ip, port);
}
}

// 退出按钮点击事件
private void QuitBtn_Click(object sender, RoutedEventArgs e)
{
if (_socket != null)
{
_socket.Dispose();
}
Application.Current.Exit();
}

// 启动服务器
private async Task StartServerAsync(string ip, int port)
{
try
{
var listener = new StreamSocketListener();
listener.ConnectionReceived += OnConnectionReceived;
await listener.BindEndpointAsync(new HostName(ip), port.ToString());

_isRunning = true;
string hostName = HostEdit.Text.Trim();
if (string.IsNullOrEmpty(hostName))
{
hostName = "Server"; // 默认服务器名称
}
ChatEdit.Text += $"{Environment.NewLine}{hostName} started on {ip}:{port}";
}
catch (Exception ex)
{
ChatEdit.Text += $"{Environment.NewLine}Server error: {ex.Message}";
}
}

private async void OnConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
var clientSocket = args.Socket;
_clientSockets.Add(clientSocket);

await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
ChatEdit.Text += $"{Environment.NewLine}Client connected: {clientSocket.Information.RemoteAddress}";
});

_ = Task.Run(() => HandleClientAsync(clientSocket));
}

// 处理客户端连接
private async Task HandleClientAsync(StreamSocket clientSocket)
{
try
{
var reader = new DataReader(clientSocket.InputStream);
reader.InputStreamOptions = InputStreamOptions.Partial;

while (true)
{
await reader.LoadAsync(1024);
if (reader.UnconsumedBufferLength == 0) break; // 客户端断开连接

string message = reader.ReadString(reader.UnconsumedBufferLength);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
ChatEdit.Text += $"{Environment.NewLine}{message}"; // 服务器显示消息
});

// 广播消息给所有客户端(不包括发送者)
BroadcastMessage(message, clientSocket);
}
}
catch (Exception ex)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
ChatEdit.Text += $"{Environment.NewLine}Client error: {ex.Message}";
});
}
finally
{
_clientSockets.Remove(clientSocket);
clientSocket.Dispose();
}
}

// 广播消息给所有客户端(不包括发送者)
private async void BroadcastMessage(string message, StreamSocket senderSocket = null)
{
foreach (var clientSocket in _clientSockets)
{
if (clientSocket != senderSocket)
{
var writer = new DataWriter(clientSocket.OutputStream);
writer.WriteString(message);
await writer.StoreAsync();
writer.DetachStream();
}
}
}

// 连接到服务器
private async Task ConnectToServerAsync(string ip, int port)
{
try
{
_socket = new StreamSocket();
await _socket.ConnectAsync(new HostName(ip), port.ToString());

ChatEdit.Text += $"{Environment.NewLine}Connected to server at {ip}:{port}";

// 启动接收消息的任务
_ = Task.Run(() => ReceiveMessagesAsync(_socket));
}
catch (Exception ex)
{
ChatEdit.Text += $"{Environment.NewLine}Connection error: {ex.Message}";
}
}

// 接收服务器消息
private async Task ReceiveMessagesAsync(StreamSocket socket)
{
try
{
var reader = new DataReader(socket.InputStream);
reader.InputStreamOptions = InputStreamOptions.Partial;

while (true)
{
await reader.LoadAsync(1024);
if (reader.UnconsumedBufferLength == 0) break; // 服务器断开连接

string message = reader.ReadString(reader.UnconsumedBufferLength);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
ChatEdit.Text += $"{Environment.NewLine}{message}"; // 客户端显示消息
});
}
}
catch (Exception ex)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
ChatEdit.Text += $"{Environment.NewLine}Receive error: {ex.Message}";
});
}
}

// 发送消息到服务器
private async void SendMessageToServer(string message)
{
if (_socket != null)
{
var writer = new DataWriter(_socket.OutputStream);
writer.WriteString(message);
await writer.StoreAsync();
writer.DetachStream();
}
}
}
}

这里是我打包过的(Appxbundle不含arm64)版本是1.0.3.0

https://www.123865.com/s/qPh5Vv-kajN
https://www.123684.com/s/qPh5Vv-kajN
好了就到这里吧。

别检查我的网站了喵 本文采用 CC BY-NC-SA 4.0 国际许可协议进行许可。 转载请注明作者及原文链接,并遵循相同方式共享原则。 链接:https://blog.nanoturtle.cn/index.php/2025/09/07/%e5%9f%ba%e4%ba%8euwp%ef%bc%88net-native%ef%bc%89%e7%9a%84%e5%a4%9a%e7%ba%bf%e7%a8%8b%e8%81%8a%e5%a4%a9%e5%ae%a4/
NanoTurtle的头像

NanoTurtle

文章作者

发表回复

textsms
account_circle
email

NanoTurtle的小窝

基于UWP(NET Native)的多线程聊天室
发布于:Mar 22, 2025 嗨嗨嗨我又来了! https://music.163.com/outchain/player?type=2&id=509626&auto=0&height=66 这几天我在编写WinUI3和UWP。因为我的小米4…
扫描二维码继续阅读
2025-09-07
登录

ACGN Android Arch Linux C# C++ IT兴趣 Linux Magisk模块 Python Python Root 权限 SEO优化 Steam Ubuntu WinUI WinUI3 三星刷机 东方Project 个人博客 中文输入法 人工智能 历史课件 同人游戏 域名管理 学生生活 改革开放 数码设备 新年快乐 新年祝福 机器学习 游戏 现代化建设 科技 空气质量 终端美化 网站迁移 网站运营 节日问候 语言设置 音乐