一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - C# - C#基于Windows服務(wù)的聊天程序(1)

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

2022-01-17 12:49波谷 C#

這篇文章主要為大家詳細(xì)介紹了C#基于Windows服務(wù)的聊天程序的第一篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

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

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

自定義協(xié)議:

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

1.新建windows服務(wù)項(xiàng)目

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

2.修改配置文件添加

?
1
2
3
4
<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ù)器(多個(gè)服務(wù)器,隔開)

3.打開chatservice右鍵添加安裝程序,此時(shí)會(huì)自動(dòng)添加projectinstaller.cs文件,文件中會(huì)默認(rèn)添加serviceprocessinstaller1和serviceinstaller1兩個(gè)組件

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

修改serviceinstaller1和serviceprocessinstaller1的屬性信息如圖

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

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

starttype屬性說明:

  automatic 指示服務(wù)在系統(tǒng)啟動(dòng)時(shí)將由(或已由)操作系統(tǒng)啟動(dòng)。如果某個(gè)自動(dòng)啟動(dòng)的服務(wù)依賴于某個(gè)手動(dòng)啟動(dòng)的服務(wù),則手動(dòng)啟動(dòng)的服務(wù)也會(huì)在系統(tǒng)啟動(dòng)時(shí)自動(dòng)啟動(dòng)。

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

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

account屬性說明:

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

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

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

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

4.完成以后打開chatservice代碼,重寫onstart和onstop方法(即服務(wù)的啟動(dòng)和停止方法)。若要重寫其它方法請(qǐng)?jiān)趕ervicebase中查看。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)容,這樣才能生成到輸出文件夾中

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

6.回到上面的重寫onstart和onstop方法

創(chuàng)建一個(gè)sockethelper類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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);//本機(jī)預(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)識(shí)</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方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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");
    }
}

至此一個(gè)簡(jiǎn)易的windows服務(wù)的聊天服務(wù)端開發(fā)完成,后續(xù)會(huì)在這基礎(chǔ)上進(jìn)行擴(kuò)展。

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

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

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

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

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

則部署腳本為

  cd c:\bin\

  installutil windowschat.exe

  卸載腳本

  installutil -u windowschat.exe

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产专区一va亚洲v天堂 | 高清视频免费 | 99久久精品免费精品国产 | 国产精品久久久久久影院 | 成人免费播放 | 波多野结衣在线观看视频 | 日韩一级片在线免费观看 | 亚洲第一综合网站 | 98成人 | 日本b站一卡二不卡三卡四卡 | 亚洲AV无码国产精品午夜久久 | 免费视屏 | 亚洲AVAV天堂AV在线网爱情 | 亚洲AV无码偷拍在线观看 | 国内精品视频一区二区三区八戒 | 国产午夜视频在线观看网站 | 青青久在线视频免费观看 | 免费高清www动漫视频播放器 | 亚洲大逼| ysl蜜桃色成人麻豆 youwu在线影院 | 天堂俺去俺来也www久久婷婷 | 欧美久久久久久久一区二区三区 | 精品国产福利一区二区在线 | h杯奶水太多h | 欧美另类老女人 | 放荡警察巨r麻麻出轨小说 范冰冰特黄xx大片 饭冈加奈子在线播放观看 法国老妇性xx在线播放 | 国产成人精品曰本亚洲77美色 | 91这里只有精品 | α级毛片 | 成年人免费观看的视频 | 天天干夜夜噜 | aaaa黄色片 | 国产一区二区三区免费在线视频 | www.片| 9热在线精品视频观看 | 91真人毛片一级在线播放 | 国产乱妇无码大片在线观看 | 久久香蕉国产免费天天 | 欧美同性猛男野外gay免费 | 国产乱码一卡二卡3卡四卡 国产乱插 | 日本不卡不码高清免费观看 |