国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

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

2020-01-24 00:34:27
字體:
來源:轉載
供稿:網友

本文將演示怎么通過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 offpath %SystemRoot%/Microsoft.NET/Framework/v4.0.30319;%path%installutil %~dp0/WindowsChat.exe%SystemRoot%/system32/sc failure "ChatService" reset= 30 actions= restart/1000pause@echo onUninstall.bat@echo offpath %SystemRoot%/Microsoft.NET/Framework/v4.0.30319;%path%installutil -u %~dp0/WindowsChat.exepause@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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 赣州市| 平果县| 鄂温| 乳源| 沐川县| 元江| 南雄市| 同德县| 东海县| 东阳市| 龙南县| 乐业县| 阳新县| 宁远县| 萍乡市| 汪清县| 焦作市| 闸北区| 灵台县| 新乡县| 六盘水市| 赣州市| 岑溪市| 农安县| 威远县| 鄂尔多斯市| 梅河口市| 宝山区| 洛宁县| 恩施市| 永德县| 佛教| 泗洪县| 新巴尔虎左旗| 武冈市| 遂平县| 铁岭市| 柏乡县| 德江县| 淳安县| 澄迈县|