目录
1.TCP服务端开发
创建控制台程序,选择.NET 8.0框架
运行时启动TCP服务监听
using LS.Standard.Helper.Logs;
using UpdateServer;
LogOperate.InitLog(1, AppDomain.CurrentDomain.BaseDirectory + "Logs\\");
TCP_Server.Start();
while (true)
{
string res = Console.ReadLine();
if (res == "quit")
{
break;
}
}
TCP服务端实现:
监听端口 13000
接收到消息,就原路返回处理的结果。
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace UpdateServer
{
public static class TCP_Server
{
private static readonly List<TcpClient> _connectedClients = new();
private static readonly object _lock = new();
public static async Task Start()
{
const int port = 13000;
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
Console.WriteLine($"TCP Server started. Listening on port {port}...");
try
{
while (true)
{
// 异步接收客户端连接
TcpClient client = await listener.AcceptTcpClientAsync();
lock (_lock)
{
_connectedClients.Add(client);
}
// 为每个客户端启动独立处理任务
_ = Task.Run(() => HandleClientAsync(client));
}
}
catch (Exception ex)
{
Console.WriteLine($"Server fatal error: {ex.Message}");
}
}
private static async Task HandleClientAsync(TcpClient client)
{
string clientId = client.Client.RemoteEndPoint?.ToString() ?? "Unknown";
Console.WriteLine($"Client connected: {clientId}");
try
{
using NetworkStream stream = client.GetStream();
byte[] buffer = new byte[4096];
while (client.Connected)
{
// 异步读取数据
int bytesRead = await stream.ReadAsync(buffer);
if (bytesRead == 0) continue;
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
//消息处理
switch (message)
{
case "UpdateServer":
string res = UpdateExecute.Check();
var data = Encoding.UTF8.GetBytes(res);
SendToClientAsync(client, data);
if (res == "OK")
{
//开始执行更新程序
Task.Run(UpdateExecute.Execute);
}
break;
}
}
}
catch (IOException ex) when (ex.InnerException is SocketException se)
{
Console.WriteLine($"Client {clientId} disconnected abruptly: {se.SocketErrorCode}");
}
finally
{
lock (_lock)
{
_connectedClients.Remove(client);
}
client.Dispose();
Console.WriteLine($"Client disconnected: {clientId}");
}
}
// 广播消息给所有连接的客户端
private static async Task BroadcastMessageAsync(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
List<Task> sendTasks = new();
lock (_lock)
{
foreach (var client in _connectedClients.Where(c => c.Connected))
{
sendTasks.Add(SendToClientAsync(client, data));
}
}
await Task.WhenAll(sendTasks);
}
private static async Task SendToClientAsync(TcpClient client, byte[] data)
{
try
{
await client.GetStream().WriteAsync(data);
}
catch (Exception ex)
{
Console.WriteLine($"Send error to {client.Client.RemoteEndPoint}: {ex.Message}");
}
}
}
}
2.部署环境
下载.NET 8.0的SDK
复制到树莓派上,我这边使用的地址是:/home/administrator/dotnetFile/
放上去之后,可以使用名称检测库文件是否可用:
sudo /home/administrator/dotnetFile/dotnet --info
然后再将控制台程序文件拷贝上去
这边使用的目录是:/home/administrator/UpdateService/
这时候可以单独用命令运行程序,检测是否正常启动
sudo /home/administrator/dotnetFile/dotnet /home/administrator/UpdateService/UpdateServer.dll
3.创建服务
创建服务文件:sudo vim /etc/systemd/system/update.service
然后将服务启动相关配置写入,里边的路径修改一下
[Unit]
Description=My .NET Service
After=network.target # 网络就绪后启动
[Service]
Type=notify # 使用.NET的systemd通知机制
WorkingDirectory=/home/administrator/UpdateService/
ExecStart=sudo /home/administrator/dotnetFile/dotnet /home/administrator/UpdateService/UpdateServer.dll
Restart=always # 崩溃时自动重启
RestartSec=10
[Install]
WantedBy=multi-user.target # 多用户模式启用
再赋予权限: sudo chmod 777 /etc/systemd/system/update.service
接着重载服务配置:sudo systemctl daemon-reload
下面就可以启动服务了:
sudo systemctl start update.service # 立即启动
sudo systemctl enable update.service # 启用开机自启
systemctl status update.service # 检查运行状态
journalctl -u myapp -f # 实时查看日志(调试必备)
4.测试连接
运行好之后,可以用TCP工具测试连接是否正常,收发数据是否正常:
验证完一切OK后,就可以尝试重启树莓派,看下是否开机启动正常