栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C# > C#教程

C#基于Windows服务的聊天程序(1)

C#教程 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C#基于Windows服务的聊天程序(1)

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

简单的消息则通过服务器转发,文件类的消息则让客户端自己建立连接进行传输。后续功能将慢慢完善。

自定义协议:

1.新建Windows服务项目

2.修改配置文件添加


  
  

说明: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.NETframeworkv4.0.30319;%path%
installutil %~dp0WindowsChat.exe
%SystemRoot%system32sc failure "ChatService" reset= 30 actions= restart/1000
pause
@echo on

Uninstall.bat
@echo off
path %SystemRoot%Microsoft.NETframeworkv4.0.30319;%path%
installutil -u %~dp0WindowsChat.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 Clients = new List();
    private WriteInfo method = null;

    /// 
    /// 创建Socket
    /// 
    /// 端口默认 11011
    /// The maximum length of the pending connections queue.
    /// 
    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;
    }

    /// 
    /// 查找客户端连接
    /// 
    /// 标识
    /// 
    private Socket Findlinked(string id)
    {
      foreach (var item in Clients)
      {
 if (item.RemoteEndPoint.ToString() == id)
   return item;
      }
      return null;
    }

    /// 
    /// 接受远程连接
    /// 
    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());
 }
      }
    }

    /// 
    /// 日志
    /// 
    /// 信息
    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);
      }
    }

    /// 
    /// 广播
    /// 
    /// 信息
    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;
 }
      }
    }

    /// 
    /// 介绍信息
    /// 
    /// 
    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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/123302.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号