首页 > 应用开发 > .net > [NewLife.Net]构建可靠的网络服务
网络程序应该注册成为系统服务,以保证其自启动以及稳定可靠运行!
这一场,讲讲怎么建立一个生产级别的网络服务。
老规矩,先上源码: https://github.com/NewLifeX/NewLife.Net
系统服务功能,由网络库的兄弟框架,X组件的Agent来支撑,以前也叫XAgent,网上搜索 NewLife.Agent 可以找到不少文章。
XAgent在X组件里面很年轻,才10年,设计于2008年,上海陆家嘴。
EchoAgent跑起来先来看看最终效果,客户端用上次的EchoTest,大家也可以telnet net.newlifex.com 1234 来看效果

左边窗口就是这次要讲的网络服务程序,工作在循环调试模式。
右边窗口是上一次的EchoTest客户端,连接左边网络服务。
客户端向服务端发送了5次数据,都得到响应,同时,服务端每秒主动向客户端发送一次本机时间。
建立一个控制台项目,通过nuget引用NewLife.Core。项目源码 https://github.com/NewLifeX/NewLife.Net/tree/master/EchoAgent
新建一个服务类 MyService,继承自泛型基类 AgentServiceBase<MyService>
Program.Main里面增加一行引导程序:
class Program
{
static void Main(String[] args) => new MyService().Main(args);
}
下面就开始慢慢完善我们的服务类MyService
public MyService()
{
ServiceName = "EchoAgent";
DisplayName = "回声服务";
Description = "这是NewLife.Net的一个回声服务示例!";
}
指定一些基本参数,看效果图可以猜到用途

服务名、显示名、描述,就这么多!
系统服务的标准动作就是启动和停止
MyNetServer _Server;
/// <summary>开始服务</summary>
/// <param name="reason"></param>
protected override void StartWork(String reason)
{
// 实例化服务端,指定端口,同时在Tcp/Udp/IPv4/IPv6上监听
var svr = new MyNetServer
{
Port = 1234,
Log = XTrace.Log,
#if DEBUG
SocketLog = XTrace.Log,
LogSend = true,
LogReceive = true,
#endif
};
svr.Start();
_Server = svr;
_timer1 = new TimerX(s => ShowStat(_Server), null, 1000, 1000) { Async = true };
_timer2 = new TimerX(s => SendTime(_Server), null, 1000, 1000) { Async = true };
base.StartWork(reason);
}
/// <summary>停止服务</summary>
/// <param name="reason"></param>
protected override void StopWork(String reason)
{
_Server.TryDispose();
_Server = null;
base.StopWork(reason);
}
private TimerX _timer1;
private TimerX _timer2;
private String _last;
/// <summary>显示服务端状态</summary>
/// <param name="ns"></param>
private void ShowStat(NetServer ns)
{
if (ns == null) return;
var msg = ns.GetStat();
if (msg == _last) return;
_last = msg;
WriteLog(msg);
}
/// <summary>向所有客户端发送时间</summary>
/// <param name="ns"></param>
private void SendTime(NetServer ns)
{
if (ns == null) return;
var str = DateTime.Now.ToFullString() + Environment.NewLine;
var buf = str.GetBytes();
ns.SendAllAsync(buf);
}
我们重载启动函数,初始化网络服务,并重启停止函数来销毁网络服务。
这里的MyNetServer从上一个例程拷贝过来。
网络服务做一个成员资源,避免被GC回收。
既然是控制台项目,先跑起来看看:

红色字体显示重要信息,黄色字体显示菜单,常用功能是235。
我们选择 5循环调试 ,其实就是在控制台里面模拟服务工作流程,让网络服务跑起来。
底下日志可以看到,它监听了4个套接字。
2是安装服务 ,也就是把当前应用安装成为Windows服务或者Linux的Systemd服务,这里特别注意,一般需要管理员权限,才能安装成功,除非关闭系统UAC。
3是启动服务 ,只有在安装了服务之后,才能看到。
所以,XAgent程序,既是开发调试控制台程序,也是安装卸载、启动停止服务的操作台,更是Windows服务程序本身!
细心的同学可以发现,安装好的Windows服务实质上就是 EchoAgent.exe -s,带有-s参数。
最后,我们把它安装到一台公网服务器上,tcp://net.newlifex.com:1234,telnet上去看看效果

服务端日志如下:
#Software: EchoAgent #ProcessID: 13592 x64 #AppDomain: EchoAgent #FileName: D:\X\NewLife.Net\Bin\Agent\EchoAgent.exe #BaseDirectory: D:\X\NewLife.Net\Bin\Agent\ #TempPath: C:\Users\Stone\AppData\Local\Temp\ #CommandLine: D:\X\NewLife.Net\Bin\Agent\EchoAgent.dll #ApplicationType: Console #CLR: 3.1.5, .NET Core 3.1.5 #OS: Microsoft Windows NT 6.2.9200.0, X3/Stone #CPU: 8 #GC: IsServerGC=False, LatencyMode=Interactive #Date: 2020-07-05 #字段: 时间 线程ID 线程池Y/网页W/普通N/定时T 线程名/任务ID 消息内容 #Fields: Time ThreadID Kind Name Message 13:18:26.412 1 N - MyNet 准备开始监听4个服务器 13:18:26.416 1 N - MyNetTcp.Start Tcp://0.0.0.0:1234 13:18:26.422 1 N - MyNet 开始监听 Tcp://0.0.0.0:1234 13:18:26.424 1 N - MyNetTcp6.Start Tcp://:::1234 13:18:26.425 1 N - MyNet 开始监听 Tcp://:::1234 13:18:26.427 1 N - MyNetUdp.Open Udp://0.0.0.0:1234 13:18:26.431 1 N - MyNet 开始监听 Udp://0.0.0.0:1234 13:18:26.432 1 N - MyNetUdp6.Open Udp://:::1234 13:18:26.433 1 N - MyNet 开始监听 Udp://:::1234 13:18:26.433 1 N - MyNet 准备就绪! 13:18:26.434 1 N - 服务启动 循环开始
至此,我们的Windows网络服务程序开发完成,并安装到公网服务器上,持续对外提供Echo服务!
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70012705/viewspace-2851596/ ,如需转载,请注明出处,否则将追究法律责任。