您尚未登录,请登录后浏览更多内容! 登录 | 立即注册

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 15466|回复: 0
打印 上一主题 下一主题

[html5] 在IIS上搭建WebSocket服务器(二)

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目

- N& G2 ?' X! O  B
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ( v9 b' i7 H* l; J! }9 B
  2. using System.Collections.Generic;
    ( T) I/ p6 C, S  X  m' `
  3. using System.Linq;
    0 u0 w; |" \# ]/ @7 h# }/ L
  4. using System.Net.WebSockets;
    , j2 c8 @; H* n9 T" d
  5. using System.Text;
    ' e5 t! Q' s2 Z$ D' C
  6. using System.Threading;  ~$ L: V3 d9 D* o- L4 l
  7. using System.Threading.Tasks;' \6 C& ?3 ^  x, c4 P
  8. using System.Web;
    2 M- Q$ _; C. }: ~/ R0 Y
  9. using System.Web.WebSockets;
    1 u( f3 X3 Z; K/ v
  10. , b& B8 N2 x( b8 h4 ~) f$ T" y

  11. / }4 M1 F' o; w2 V( s8 l$ s
  12. namespace WebApplicationWebsocketHandler3 S) V$ G' I5 N  \; H- o1 S1 {
  13. {7 L8 ^% Z4 H" J4 p
  14.     /// <summary>* J7 w8 ?$ r8 K3 L* `2 z, b' F3 U
  15.     /// 离线消息
    8 w; U" v/ d) E. U, o/ z. H
  16.     /// </summary>
    $ V9 n  J: f& ?; P& u5 i  v
  17.     public class MessageInfo, }  b; y1 D" M$ J
  18.     {
    ( ?! X, j/ B6 T
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)+ }; C6 X, C4 ?6 Y: D/ @8 e4 y& ~
  20.         {- g8 Q) F$ t$ h( f" u
  21.             MsgTime = _MsgTime;7 l" ~( @  Y0 T3 R
  22.             MsgContent = _MsgContent;; n+ k" G; H: f$ b
  23.         }
    / ~& f6 _! k; ]
  24.         public DateTime MsgTime { get; set; }
    * S, `* R. D/ [1 F/ |4 c( k" k9 Q
  25.         public ArraySegment<byte> MsgContent { get; set; }
    - d+ \% U$ s( l9 ^' M: A# p0 g. u
  26.     }
    6 M7 U7 o9 {  g0 s' x2 |# w
  27. * o7 c9 x9 _* N. w% E
  28. ) w1 l' ?* u1 }) T" }; `; P! J
  29. 7 ?' B- O! x; ]1 r
  30. * `* X- d* G; f7 H" x
  31.     /// <summary>
    5 a1 ]# q, o0 C' G
  32.     /// Handler1 的摘要说明0 K0 ^# X* ~  h
  33.     /// </summary>
    ' V) W: x4 W" O+ x9 N; f4 |
  34.     public class Handler1 : IHttpHandler
    9 _3 J6 F2 `1 v9 Y' |
  35.     {- P! q1 ?6 `3 \9 V7 I# E+ l
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    2 i6 l& v0 u8 {8 A
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池( ?! L' e- x7 ]; ]6 n$ n
  38.         public void ProcessRequest(HttpContext context)' q, k7 n% F9 f7 U8 x: U
  39.         {- a7 y! X8 ?4 b, l6 D$ X( c
  40.             //context.Response.ContentType = "text/plain";% \! E. w: w; i
  41.             //context.Response.Write("Hello World");
    4 w( N4 P+ {$ s) h
  42.             if (context.IsWebSocketRequest)3 |- H7 T! l; @; g& F% ~# P
  43.             {
    % A4 n5 p/ g- R2 E" Z( O( t3 F- B# Z
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    , o: U4 u* F0 c' b: w- ^2 ?( U
  45.             }
      ^0 K% v5 o% S3 z. V/ J
  46.         }
    . `% }. S# q+ ]9 Y/ g* E

  47. # h) S7 K( U# m( E* u# W2 L; E
  48.         private async Task ProcessChat(AspNetWebSocketContext context)/ O* ^0 R- v# C$ t, m- Y7 z
  49.         {
    5 E7 l6 Y$ A4 i, [3 j: F1 W
  50.             WebSocket socket = context.WebSocket;
    . s% D2 y* d) O* b$ l$ i& V
  51.             string user = context.QueryString["user"].ToString();
    & {' I0 m4 Y; L$ X6 ^, ~
  52. 4 w4 M+ u" I5 ]0 S- o  a( v
  53.             try& J4 T: N" [2 m! N
  54.             {
    2 k# j, ]( l+ p$ @6 D0 @
  55.                 #region 用户添加连接池! u! r5 e* A) S2 U5 u
  56.                 //第一次open时,添加到连接池中
    4 h* I6 W; g0 H/ h0 H
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    9 W, ]9 G$ ]8 o# C) S1 o  U* G8 @
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加5 a, C) j. p4 h9 x& C6 U7 w4 J. t
  59.                 else
    2 _$ Q- X  _. N' R0 S  b
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    % y( Y  q! ~, P* ~1 l: U
  61.                         CONNECT_POOL[user] = socket;8 w2 e; n  {3 Y7 W, s3 q6 i
  62.                 #endregion
    * x+ ~" J: x8 L1 q5 Y3 z% O

  63. # f- w3 E" }& k9 L) j; D
  64.                 #region 离线消息处理% Y# P# F" F* Z
  65.                 if (MESSAGE_POOL.ContainsKey(user))( ]/ F# G: h6 o# }/ V
  66.                 {+ L* \( j' A8 w/ e* N
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    # \; A3 X. L0 z8 e" T) M
  68.                     foreach (MessageInfo item in msgs)& c9 A2 z9 M, U2 f+ \- T
  69.                     {+ U  u$ T1 w7 ~$ j5 K
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);  v: a; o, S) i- [; b! A
  71.                     }
    1 P5 z4 E, c4 T. J) g( ^
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ( @4 ^8 H' i4 y/ `, L
  73.                 }
    : e! i4 Z5 k5 n1 _$ O3 x
  74.                 #endregion' \0 \* n# D  L! J( Q

  75. # }. b% Q6 B" {+ q8 U
  76.                 string descUser = string.Empty;//目的用户* B8 J# {% Y' Z# O/ d9 @- [! _
  77.                 while (true)
    ; _. M" e3 V* z$ {2 N8 s! J4 f9 \
  78.                 {+ Q; f! b4 s$ }4 N
  79.                     if (socket.State == WebSocketState.Open)
    2 t( Z: h4 z( |; Y9 z; Z
  80.                     {8 k4 p; C0 ^; ?% X, i4 \& k5 h+ L
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    6 X) b7 d  T& v! N$ c5 T2 [' X
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    9 d: s/ {: Q2 N( L( a3 J- e! j
  83. ! V0 Y: x5 g7 h' S
  84.                         #region 消息处理(字符截取、消息转发)# N3 Y4 M0 s& U. d
  85.                         try$ Y0 R# U9 t; H2 o
  86.                         {
    ' T1 L$ d1 ]0 w& {) z& d0 j
  87.                             #region 关闭Socket处理,删除连接池$ b- N/ L" [% Q+ c0 e: s2 o
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    0 J  X/ t$ N: y( T; Q7 }! e7 J0 V
  89.                             {- j: c; d# }5 E
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池$ a; ]5 j* m/ h/ I- c- \3 D0 M% N
  91.                                 break;0 ]7 U% I- {4 u  j  m* U! F
  92.                             }
    ) u  T6 [+ A4 B" [" L
  93.                             #endregion
    $ f. G8 U  o; M5 S& q9 t

  94. / K, X( ^/ {7 O; I5 }" M
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    , M) l' T! r7 `. @! }9 P% W) ]% H
  96.                             string[] msgList = userMsg.Split('|');
    % D4 X( N8 \8 D
  97.                             if (msgList.Length == 2)
    " }  h& u! B  k  I" c8 ^- r
  98.                             {
    - i- `( R) y- @. ^( d7 ]' Q
  99.                                 if (msgList[0].Trim().Length > 0)
    " e7 s  b9 h( p7 j. B- R+ B
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户5 `& c. V( E* u, O& u* q
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    4 O- r9 D8 F  I' w: B  k3 K5 ]% C
  102.                             }
    7 X8 u, @0 Z/ {0 ^
  103.                             else7 v) f: M! D$ g& [$ R
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));8 x% j" y  ~! V2 ]5 N! J
  105. / W9 b' s& p8 S& Q) h0 a; N% i! G
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    7 ?) p) ]& [& d. l3 V
  107.                             {
    $ A" F1 ]4 }9 G2 ^4 T: {0 Q
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端& O: N( g' o5 Q! R; k' k
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)% Y. U3 K% Y9 U8 l1 t1 v* Q8 Q# u
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);- E$ I8 B( N* v; C, S. Y& Z  ^$ t* Y
  111.                             }
    5 Y1 Y# c" I& C$ l7 i
  112.                             else
    + m7 ^& s! P2 C5 s$ i+ z
  113.                             {5 v6 C8 M+ u9 ]" D6 m
  114.                                 Task.Run(() =>
    ! ~2 m1 h1 R( @
  115.                                 {
    ( f0 t1 w1 ]) O! P1 k
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中, B  `, }7 }# T4 B+ c, J
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    ) t: z* m8 Z# a8 n* `4 `
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息" q& Q5 K. x6 ~0 S* C
  119.                                 });
    0 U" {1 d4 q/ Z
  120.                             }
    - T$ n  @5 N' h8 f, x3 @
  121.                         }$ d' j' e3 S* K6 s
  122.                         catch (Exception exs)# K. a6 m# n$ l) B' G
  123.                         {
    $ f0 f6 z' L4 c& G4 D( R6 t; C
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息; a& w, K5 ~6 ]; R
  125.                         }& L$ ]% w. N  d8 \% A  f7 [( R
  126.                         #endregion
    ( r( V& ?8 L& m9 {; I, e8 {
  127.                     }4 _" u4 Q+ @0 s$ X2 F$ N7 ?
  128.                     else' _/ A1 U1 ^4 Q( x& e
  129.                     {
    - w" _8 \& Y0 ?3 T/ r
  130.                         break;0 f3 o! v, ?+ U0 S8 s) g
  131.                     }
    , Z( z) Q3 d- c' n  d) G+ E
  132.                 }//while end; p: [3 L' a, f  k3 O- P* K$ B) z
  133.             }& y# D7 V( @( r. q
  134.             catch (Exception ex)
    + }( N$ f+ V2 M7 r- k
  135.             {
    5 z6 l; ]5 P2 e
  136.                 //整体异常处理
    7 u2 s9 R! w* A* ]. _
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);- k+ v% k$ ~. X3 o2 ^* c/ W
  138.             }0 @$ a% z% W2 R7 ]8 y. R: {# K" K
  139.         }6 l! d7 I) R% b5 ~
  140. ) i6 m2 `( ]+ }+ B2 E" {8 {7 y
  141. ( W+ M/ y$ o8 F$ I* ~
  142.         public bool IsReusable, u. b( ?% b( l# ^0 v* a- J
  143.         {
    # r1 O! N  B7 w6 x) ^& v7 F
  144.             get
    & B4 x5 a8 `4 h; X  b  s$ C
  145.             {; J2 ^8 T: ~+ V4 [5 _
  146.                 return false;
    0 d; Q6 d" j0 O7 v; ?
  147.             }
    7 s# `  B  R/ W* D0 x
  148.         }6 {# V3 d2 f5 j" y- z( i1 u
  149.     }; q: _# l: ]$ u# f
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
$ S* d4 ^) L  f' `; m
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-19 22:45 , Processed in 0.057749 second(s), 23 queries .

Copyright © 2001-2026 Powered by cncml! X3.2. Theme By cncml!