本文将演示怎么通过C#开发部署一个Windows服务,该服务提供各客户端的信息通讯,适用于局域网。采用TCP协议,单一服务器连接模式为一对多;多台服务器的情况下,当客户端连接数超过预设值时可自动进行负载转移,当然也可手动切换服务器,这种场景在实际项目中应用广泛。

简单的消息则通过服务器转发,文件类的消息则让客户端自己建立连接进行传输。后续功能将慢慢完善。
自定义协议:
1.新建Windows服务项目
2.修改配置文件添加
<appSettings> <add key="maxQueueCount" value="10"/> <add key="failoverServer" value="192.168.250.113,192.168.250.141"/> </appSettings>
说明:maxQueueCount为最大连接数,failoverServer故障转移备用服务器(多个服务器,隔开)
3.打开ChatService右键添加安装程序,此时会自动添加ProjectInstaller.cs文件,文件中会默认添加serviceProcessInstaller1和serviceInstaller1两个组件
修改serviceInstaller1和serviceProcessInstaller1的属性信息如图
StartType属性说明:
Automatic 指示服务在系统启动时将由(或已由)操作系统启动。如果某个自动启动的服务依赖于某个手动启动的服务,则手动启动的服务也会在系统启动时自动启动。
Disabled 指示禁用该服务,以便它无法由用户或应用程序启动。
Manual 指示服务只由用户(使用“服务控制管理器”)或应用程序手动启动。
Account属性说明:
LocalService 充当本地计算机上非特权用户的帐户,该帐户将匿名凭据提供给所有远程服务器。
LocalSystem 服务控制管理员使用的帐户,它具有本地计算机上的许多权限并作为网络上的计算机。
NetworkService 提供广泛的本地特权的帐户,该帐户将计算机的凭据提供给所有远程服务器。
User 由网络上特定的用户定义的帐户。如果为 ServiceProcessInstaller.Account 成员指定 User,则会使系统在安装服务时提示输入有效的用户名和密码,除非您为 ServiceProcessInstaller 实例的 Username 和 Password 这两个属性设置值。
4.完成以后打开ChatService代码,重写OnStart和OnStop方法(即服务的启动和停止方法)。若要重写其它方法请在ServiceBase中查看。
5.在项目中添加服务注册和卸载脚本文件
Install.bat @echo off path %SystemRoot%\Microsoft.NET\Framework\v4.0.30319;%path% installutil %~dp0\WindowsChat.exe %SystemRoot%\system32\sc failure "ChatService" reset= 30 actions= restart/1000 pause @echo on Uninstall.bat @echo off path %SystemRoot%\Microsoft.NET\Framework\v4.0.30319;%path% installutil -u %~dp0\WindowsChat.exe pause @echo on
说明:%~dp0 表示bat文件所在的目录
文件属性选择 始终复制-内容,这样才能生成到输出文件夹中
6.回到上面的重写OnStart和OnStop方法
创建一个SocketHelper类
namespace WindowsChat
{
public delegate void WriteInfo(string info);
public class SocketHelper
{
#region 构造函数
public SocketHelper()
{
}
public SocketHelper(WriteInfo method)
{
this.method = method;
}
#endregion
public static Socket LocalSocket = null;
private object lockObj = new object();
public static List<Socket> Clients = new List<Socket>();
private WriteInfo method = null;
/// <summary>
/// 创建Socket
/// </summary>
/// <param name="port">端口默认 11011</param>
/// <param name="backlog">The maximum length of the pending connections queue.</param>
/// <returns></returns>
public Socket Create(int port = 11011, int backlog = 100)
{
if (LocalSocket == null)
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, port);//本机预使用的IP和端口
LocalSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
LocalSocket.Bind(ipEndPoint);
LocalSocket.Listen(backlog);
}
return LocalSocket;
}
/// <summary>
/// 查找客户端连接
/// </summary>
/// <param name="id">标识</param>
/// <returns></returns>
private Socket FindLinked(string id)
{
foreach (var item in Clients)
{
if (item.RemoteEndPoint.ToString() == id)
return item;
}
return null;
}
/// <summary>
/// 接受远程连接
/// </summary>
public void Accept()
{
if (LocalSocket != null)
{
while (true)
{
Socket client = LocalSocket.Accept();
Thread thread = new Thread(new ParameterizedThreadStart(Revice));
thread.Start(client);
WriteLog("客户端:" + client.RemoteEndPoint.ToString() + " 接入");
lock (lockObj)
{
Clients.Add(client);
}
BroadCast("ADD|" + client.RemoteEndPoint.ToString());
}
}
}
/// <summary>
/// 日志
/// </summary>
/// <param name="info">信息</param>
private void WriteLog(string info)
{
using (FileStream fs = new FileStream("C:\\chatservice.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
{
sw.WriteLine(info);
}
}
if (method != null)
{
method(info);
}
}
/// <summary>
/// 广播
/// </summary>
/// <param name="info">信息</param>
public void BroadCast(string info)
{
foreach (var item in Clients)
{
try
{
item.Send(Encoding.UTF8.GetBytes(info));
}
catch (Exception ex)
{
WriteLog(item.RemoteEndPoint.ToString() + ex.Message);
continue;
}
}
}
/// <summary>
/// 介绍信息
/// </summary>
/// <param name="client"></param>
public void Revice(object client)
{
Socket param = client as Socket;
var remoteName = param.RemoteEndPoint.ToString();
if (param != null)
{
int res = 0;
while (true)
{
byte[] buffer = new byte[10240];
int size = param.ReceiveBufferSize;
try
{
res = param.Receive(buffer);
}
catch (SocketException ex)
{
if (ex.SocketErrorCode == SocketError.ConnectionReset)
{
Clients.Remove(param);
WriteLog("客户端:" + remoteName + "断开连接1");
BroadCast("REMOVE|" + remoteName);
param.Close();
return;
}
}
if (res == 0)
{
Clients.Remove(param);
WriteLog("客户端:" + remoteName + "断开连接2");
BroadCast("REMOVE|" + remoteName);
param.Close();
return;
}
var clientMsg = Encoding.UTF8.GetString(buffer, 0, res);
WriteLog(string.Format("收到客户端{0}命令:{1}", remoteName, clientMsg));
if (clientMsg == "GETALL")
{
StringBuilder sb = new StringBuilder();
foreach (var item in Clients)
{
sb.AppendFormat("{0}|", item.RemoteEndPoint.ToString());
}
param.Send(Encoding.UTF8.GetBytes("ALL|" + sb.ToString()));
}
else if (clientMsg == "OFFLINE")
{
if (Clients.Contains(param))
{
Clients.Remove(param);
WriteLog("客户端:" + remoteName + "断开连接2");
BroadCast("REMOVE|" + remoteName);
param.Close();
return;
}
}
else if (clientMsg.StartsWith("TRANST|"))
{
var msgs = clientMsg.Split('|');
var toSocket = FindLinked(msgs[1]);
if (toSocket != null)
{
WriteLog(remoteName + "发给" + msgs[1] + "的消息" + msgs[2]);
toSocket.Send(Encoding.UTF8.GetBytes("TRANSF|" + remoteName + "|" + msgs[2]));
}
}
}
}
}
}
}
重写OnStart和OnStop方法
public partial class ChatService : ServiceBase
{
SocketHelper helper;
Thread mainThread;
public ChatService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (helper == null)
{
helper = new SocketHelper();
}
helper.Create();
mainThread = new Thread(new ThreadStart(helper.Accept));
mainThread.IsBackground = true;
mainThread.Start();
}
protected override void OnStop()
{
helper.BroadCast("SHUTDOWN");
}
}
至此一个简易的Windows服务的聊天服务端开发完成,后续会在这基础上进行扩展。
运行install.bat(以管理员身份运行)如图
7.运行 services.msc查找到ChatService服务,能正常启动停止说明部署成功!
当然你也可以将InstallUtil.exe拷贝到执行文件所在目录,比如c:\bin\
则部署脚本为
cd c:\bin\
InstallUtil WindowsChat.exe
卸载脚本
InstallUtil -u WindowsChat.exe
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# C#
# Windows
# 聊天程序
# c# 实现语音聊天的实战示例
# C# Socket编程实现简单的局域网聊天器的示例代码
# C#使用Socket实现服务器与多个客户端通信(简单的聊天系统)
# C#使用Socket实现局域网聊天
# 基于c#用Socket做一个局域网聊天工具
# 分享一个C#编写简单的聊天程序(详细介绍)
# C#制作简单的多人在线即时交流聊天室
# C#基于UDP实现的P2P语音聊天工具
# C#实现简单聊天程序的方法
# c#实现多线程局域网聊天系统
# C#聊天程序服务端与客户端完整实例代码
# c#多线程网络聊天程序代码分享(服务器端和客户端)
# c#基于WinForm的Socket实现简单的聊天室 IM
# 客户端
# 重写
# 如图
# 提供给
# 机上
# 启动时
# 应用程序
# 连接数
# 自动启动
# 多个
# 在这
# 基础上
# 适用于
# 右键
# 会在
# 也可
# 请在
# 这两个
# 自定义
# 管理器
相关文章:
家具网站制作软件,家具厂怎么跑业务?
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
微信推文制作网站有哪些,怎么做微信推文,急?
深圳网站制作案例,网页的相关名词有哪些?
音乐网站服务器如何优化API响应速度?
如何在Windows环境下新建FTP站点并设置权限?
如何用5美元大硬盘VPS安全高效搭建个人网站?
专业网站设计制作公司,如何制作一个企业网站,建设网站的基本步骤有哪些?
商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?
宠物网站制作html代码,有没有专门介绍宠物如何养的网站啊?
定制建站流程步骤详解:一站式方案设计与开发指南
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
设计网站制作公司有哪些,制作网页教程?
油猴 教程,油猴搜脚本为什么会网页无法显示?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
如何在局域网内绑定自建网站域名?
如何制作一个表白网站视频,关于勇敢表白的小标题?
IOS倒计时设置UIButton标题title的抖动问题
如何配置支付宝与微信支付功能?
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
用v-html解决Vue.js渲染中html标签不被解析的问题
南京做网站制作公司,南京哈发网络有限公司,公司怎么样,做网页美工DIV+CSS待遇怎么样?
建站168自助建站系统:快速模板定制与SEO优化指南
建站之星如何助力网站排名飙升?揭秘高效技巧
建站之星展会模板:智能建站与自助搭建高效解决方案
如何通过IIS搭建网站并配置访问权限?
,在苏州找工作,上哪个网站比较好?
c# 在ASP.NET Core中管理和取消后台任务
如何快速搭建虚拟主机网站?新手必看指南
常州自助建站费用包含哪些项目?
建站ABC备案流程中有哪些关键注意事项?
小型网站制作HTML,*游戏网站怎么搭建?
如何用PHP工具快速搭建高效网站?
如何快速搭建响应式可视化网站?
制作网页的网站有哪些,电脑上怎么做网页?
专业网站制作服务公司,有哪些网站可以免费发布招聘信息?
网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?
如何在万网自助建站平台快速创建网站?
,有什么在线背英语单词效率比较高的网站?
香港服务器租用费用高吗?如何避免常见误区?
在线制作视频的网站有哪些,电脑如何制作视频短片?
临沂网站制作企业,临沂第三中学官方网站?
网站制作员失业,怎样查看自己网站的注册者?
大型企业网站制作流程,做网站需要注册公司吗?
建站之星代理商如何保障技术支持与售后服务?
c# Task.ConfigureAwait(true) 在什么场景下是必须的
建站之星安装步骤有哪些常见问题?
,网页ppt怎么弄成自己的ppt?
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
*请认真填写需求信息,我们会在24小时内与您取得联系。