欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2017年07月19日 15:28:43   作者:波谷  
這篇文章主要為大家詳細(xì)介紹了C#基于Windows服務(wù)的聊天程序的第一篇,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文將演示怎么通過C#開發(fā)部署一個Windows服務(wù),該服務(wù)提供各客戶端的信息通訊,適用于局域網(wǎng)。采用TCP協(xié)議,單一服務(wù)器連接模式為一對多;多臺服務(wù)器的情況下,當(dāng)客戶端連接數(shù)超過預(yù)設(shè)值時可自動進行負(fù)載轉(zhuǎn)移,當(dāng)然也可手動切換服務(wù)器,這種場景在實際項目中應(yīng)用廣泛。

簡單的消息則通過服務(wù)器轉(zhuǎn)發(fā),文件類的消息則讓客戶端自己建立連接進行傳輸。后續(xù)功能將慢慢完善。

自定義協(xié)議:

1.新建Windows服務(wù)項目

2.修改配置文件添加

<appSettings>
  <add key="maxQueueCount" value="10"/>
  <add key="failoverServer" value="192.168.250.113,192.168.250.141"/>
</appSettings>

說明:maxQueueCount為最大連接數(shù),failoverServer故障轉(zhuǎn)移備用服務(wù)器(多個服務(wù)器,隔開)

3.打開ChatService右鍵添加安裝程序,此時會自動添加ProjectInstaller.cs文件,文件中會默認(rèn)添加serviceProcessInstaller1和serviceInstaller1兩個組件

修改serviceInstaller1和serviceProcessInstaller1的屬性信息如圖

StartType屬性說明:

  Automatic 指示服務(wù)在系統(tǒng)啟動時將由(或已由)操作系統(tǒng)啟動。如果某個自動啟動的服務(wù)依賴于某個手動啟動的服務(wù),則手動啟動的服務(wù)也會在系統(tǒng)啟動時自動啟動。

  Disabled 指示禁用該服務(wù),以便它無法由用戶或應(yīng)用程序啟動。

  Manual 指示服務(wù)只由用戶(使用“服務(wù)控制管理器”)或應(yīng)用程序手動啟動。

Account屬性說明:

  LocalService    充當(dāng)本地計算機上非特權(quán)用戶的帳戶,該帳戶將匿名憑據(jù)提供給所有遠(yuǎn)程服務(wù)器。

  LocalSystem    服務(wù)控制管理員使用的帳戶,它具有本地計算機上的許多權(quán)限并作為網(wǎng)絡(luò)上的計算機。

  NetworkService    提供廣泛的本地特權(quán)的帳戶,該帳戶將計算機的憑據(jù)提供給所有遠(yuǎn)程服務(wù)器。

  User    由網(wǎng)絡(luò)上特定的用戶定義的帳戶。如果為 ServiceProcessInstaller.Account 成員指定 User,則會使系統(tǒng)在安裝服務(wù)時提示輸入有效的用戶名和密碼,除非您為 ServiceProcessInstaller 實例的 Username 和 Password 這兩個屬性設(shè)置值。

4.完成以后打開ChatService代碼,重寫OnStart和OnStop方法(即服務(wù)的啟動和停止方法)。若要重寫其它方法請在ServiceBase中查看。

5.在項目中添加服務(wù)注冊和卸載腳本文件

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文件所在的目錄

文件屬性選擇 始終復(fù)制-內(nèi)容,這樣才能生成到輸出文件夾中

6.回到上面的重寫OnStart和OnStop方法

創(chuàng)建一個SocketHelper類

namespace WindowsChat
{
  public delegate void WriteInfo(string info);

  public class SocketHelper
  {
    #region 構(gòu)造函數(shù)
    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>
    /// 創(chuàng)建Socket
    /// </summary>
    /// <param name="port">端口默認(rèn) 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);//本機預(yù)使用的IP和端口
        LocalSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        LocalSocket.Bind(ipEndPoint);
        LocalSocket.Listen(backlog);
      }
      return LocalSocket;
    }

    /// <summary>
    /// 查找客戶端連接
    /// </summary>
    /// <param name="id">標(biāo)識</param>
    /// <returns></returns>
    private Socket FindLinked(string id)
    {
      foreach (var item in Clients)
      {
        if (item.RemoteEndPoint.ToString() == id)
          return item;
      }
      return null;
    }

    /// <summary>
    /// 接受遠(yuǎn)程連接
    /// </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("收到客戶端{(lán)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 + "發(fā)給" + 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服務(wù)的聊天服務(wù)端開發(fā)完成,后續(xù)會在這基礎(chǔ)上進行擴展。

運行install.bat(以管理員身份運行)如圖

7.運行 services.msc查找到ChatService服務(wù),能正常啟動停止說明部署成功!

當(dāng)然你也可以將InstallUtil.exe拷貝到執(zhí)行文件所在目錄,比如c:\bin\

則部署腳本為

  cd c:\bin\

  InstallUtil WindowsChat.exe

  卸載腳本

  InstallUtil -u WindowsChat.exe

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#通過IComparable實現(xiàn)ListT.sort()排序

    C#通過IComparable實現(xiàn)ListT.sort()排序

    這篇文章主要介紹了C#通過IComparable實現(xiàn)ListT.sort()排序的方法,可實現(xiàn)自定義的排序方法,是非常實用的技巧,需要的朋友可以參考下
    2014-09-09
  • c#動態(tài)調(diào)用Webservice的兩種方法實例

    c#動態(tài)調(diào)用Webservice的兩種方法實例

    這篇文章介紹了c#動態(tài)調(diào)用Webservice的兩種方法實例,有需要的朋友可以參考一下
    2013-08-08
  • C# Bitmap 復(fù)制的小例子

    C# Bitmap 復(fù)制的小例子

    這篇文章介紹了C# Bitmap 復(fù)制的小例子,有需要的朋友可以參考一下
    2013-10-10
  • 詳解如何利用C#實現(xiàn)漢字轉(zhuǎn)拼音功能

    詳解如何利用C#實現(xiàn)漢字轉(zhuǎn)拼音功能

    這篇文章主要為大家詳細(xì)介紹了如何利用C#實現(xiàn)漢字轉(zhuǎn)拼音的功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12
  • Unity3D實現(xiàn)攝像機鏡頭移動并限制角度

    Unity3D實現(xiàn)攝像機鏡頭移動并限制角度

    這篇文章主要為大家詳細(xì)介紹了Unity3D實現(xiàn)攝像機鏡頭移動并限制角度,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C# 對XML基本操作代碼總結(jié)

    C# 對XML基本操作代碼總結(jié)

    C# 對XML基本操作包括讀取節(jié)點的數(shù)據(jù),添加節(jié)點。讀取節(jié)點屬性,修改節(jié)點屬性等
    2011-10-10
  • C#圖表算法之無向圖

    C#圖表算法之無向圖

    這篇文章介紹了C#圖表算法之無向圖,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • C# Datagridview綁定List方法代碼

    C# Datagridview綁定List方法代碼

    這篇文章主要介紹了C# Datagridview綁定List方法代碼,在進行C#數(shù)據(jù)庫程序設(shè)計時非常具有實用價值,需要的朋友可以參考下
    2014-10-10
  • C#拼圖游戲編寫代碼(2)

    C#拼圖游戲編寫代碼(2)

    這篇文章主要為大家詳細(xì)介紹了C#拼圖游戲的編寫代碼下篇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • C#基于面向過程計算加權(quán)平均分的方法

    C#基于面向過程計算加權(quán)平均分的方法

    這篇文章主要介紹了C#基于面向過程計算加權(quán)平均分的方法,涉及C#數(shù)學(xué)運算的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07

最新評論