cncml手绘网

标题: 在IIS上搭建WebSocket服务器(二) [打印本页]

作者: admin    时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目

: l4 e, l/ {& g6 y( m
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    ) M4 W) p/ k9 B1 m
  2. using System.Collections.Generic;  Q7 ]  G1 y2 D6 M! Y  u
  3. using System.Linq;' J1 m% X( ^2 u  y. b6 D
  4. using System.Net.WebSockets;
      r, u1 H7 T. I7 ~, y+ `+ g3 S0 o
  5. using System.Text;
    % |# ~; g( y- @4 t  X  T
  6. using System.Threading;+ c' O% h: _' o3 N$ n( D; P5 A$ y# X
  7. using System.Threading.Tasks;
    2 z( ]1 m$ U' z; ]
  8. using System.Web;$ _5 f: E/ g- Q/ b9 x6 F3 j
  9. using System.Web.WebSockets;
    ) `1 I& `  A( H- h) J* M0 M9 r6 o
  10. 8 ?& j) W0 J: M* h5 R

  11. ! B/ L  O: c: |
  12. namespace WebApplicationWebsocketHandler
    ' }* X# K) `7 R7 i+ h! y
  13. {
    ! `' S) s8 N, u! O: ^+ E" V
  14.     /// <summary>/ m. d! F4 Y% h& q) p& {, s2 y
  15.     /// 离线消息7 I/ `( T) R. Q9 g* A9 n5 T
  16.     /// </summary>' R4 J  e& N2 j4 U6 M3 _, h
  17.     public class MessageInfo
    / X& x% j7 h  g( J
  18.     {
    5 p, }. o# N, B5 W6 t0 s" p% s5 W! {
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)9 f1 T" l2 |0 b
  20.         {0 ^( N2 K) p( b3 z) F5 J
  21.             MsgTime = _MsgTime;) l( ?4 C7 n# ^6 E
  22.             MsgContent = _MsgContent;
    ' x9 q% f# y! g* Y/ A$ y
  23.         }
    4 x' C' m! f2 n. j9 I3 J
  24.         public DateTime MsgTime { get; set; }
    5 x4 f% B9 P# j* k/ d
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ; h" e3 j2 S' I3 s( E/ k8 T1 I
  26.     }
    9 o, k- v* s3 B! O6 A2 o

  27. 5 b1 [/ `# [/ y1 C( N6 e
  28. , ^9 b% |8 y* ?$ W+ {$ s) f
  29. ; `5 l6 M3 r7 X5 ~

  30. ; G. q/ j* D8 [# M0 [
  31.     /// <summary>: j9 x) \' d' a
  32.     /// Handler1 的摘要说明
    ! {$ I8 E6 h0 U% l% n+ u
  33.     /// </summary>7 V# Q/ D' V; ]9 t5 y
  34.     public class Handler1 : IHttpHandler
    9 T, j/ k3 |" L
  35.     {4 J8 t  d# S! z% k2 q. B5 G
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池/ ~9 d4 w# P  b8 x
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池" U# ~$ C1 ?1 Z
  38.         public void ProcessRequest(HttpContext context)$ [5 R. a* D  b
  39.         {
    # a- F% p  N( v; t) x2 l
  40.             //context.Response.ContentType = "text/plain";, f% `9 d% ^' ~2 @: O
  41.             //context.Response.Write("Hello World");
    2 [) I0 T: ^" `3 h2 a
  42.             if (context.IsWebSocketRequest)  h7 C; Q) T$ M7 `) N! y( {! G% ^
  43.             {4 }+ d0 R* h5 n4 G# }$ ?8 b
  44.                 context.AcceptWebSocketRequest(ProcessChat);) @" D. I% D# [8 _
  45.             }
    " S0 f! m) N# D8 {- G+ o
  46.         }9 U0 l$ n( x& F8 A
  47. 5 d9 i. Z' y$ N4 |
  48.         private async Task ProcessChat(AspNetWebSocketContext context)2 ^6 j9 o  u9 J: q1 u! ^/ G
  49.         {
    ! s; C2 k# h6 C! u: T% A3 g2 W5 `# F
  50.             WebSocket socket = context.WebSocket;
    $ t- ~  E6 W  O8 n5 `; Y
  51.             string user = context.QueryString["user"].ToString();
    ) N. i5 ]$ r+ R; H; ~, I5 e) w8 w! D

  52. * m( [. h8 @, ~
  53.             try' `  s2 J4 _) b0 A
  54.             {
    : Z5 L+ U7 W$ K0 E
  55.                 #region 用户添加连接池
    4 K1 Z: r9 I% k+ p0 U# F1 [
  56.                 //第一次open时,添加到连接池中
    1 @, ]4 n) J( }0 D5 i
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    4 Z( o) f8 n5 @
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    2 h2 l% d7 t# I
  59.                 else
    5 z5 K+ h, x- R& r7 D( F
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新0 l7 B3 \# X& l, H+ K9 }
  61.                         CONNECT_POOL[user] = socket;3 @* O2 {, t9 i, }* W% \. b
  62.                 #endregion1 h+ K) j  K8 v, _! @
  63. 1 l. B  |% j& m# P2 \
  64.                 #region 离线消息处理
    ; C! x9 X. i" V$ [
  65.                 if (MESSAGE_POOL.ContainsKey(user))& Y! ]% Z2 Z" [2 w3 k
  66.                 {
      q) {/ |& k% j5 {0 A5 {1 B7 _
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    2 `4 d* D& ?1 T- c6 [1 T
  68.                     foreach (MessageInfo item in msgs)
    7 W8 c' ?7 @/ h( |) B
  69.                     {
    ! v6 \; Y3 i& u! S
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    7 l5 m+ p* H  m7 W+ A: T# b8 ?- v
  71.                     }0 \- g, z3 M/ b  l, W2 f* a
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    : t. i/ Q! @7 G/ q. \5 B
  73.                 }
    3 D* X) d+ W6 p( i7 a2 r
  74.                 #endregion8 [0 |% O- H. A! @
  75. 0 ^+ `" m9 z2 A: A3 k' U
  76.                 string descUser = string.Empty;//目的用户
    " V" ]: R; _/ _; W- M0 z. ]
  77.                 while (true)
    1 Z) J* R. d+ {5 q* N2 P5 `
  78.                 {! I' d& a" l$ u  b1 b' \0 M5 P
  79.                     if (socket.State == WebSocketState.Open)) i/ T/ O! e- r* N, [! u
  80.                     {. W6 ?* C0 J0 F0 c% M
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);& M/ e2 V- b- X, n/ p1 K
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    % v' U: j  H+ v3 i! n

  83. . N! D0 X* @1 i% A: E* [( ]! r
  84.                         #region 消息处理(字符截取、消息转发)* \2 j; Y; Y  o
  85.                         try
    + K# D& T- g0 {
  86.                         {
    & b4 v$ d; J% P! O
  87.                             #region 关闭Socket处理,删除连接池4 e2 p: ?9 E# r2 {4 B. u; m
  88.                             if (socket.State != WebSocketState.Open)//连接关闭, R5 ?. L/ n# H2 `9 x  X
  89.                             {
    3 D+ y- i' Y$ o* v% {3 C
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    / q6 W5 N( m+ T  i& d
  91.                                 break;, B) q- q( f" t5 w% V2 m( }: J
  92.                             }9 Y$ s2 `2 c; d
  93.                             #endregion6 F6 v, V: W" J7 u  l  q2 x; Z: ?

  94. 9 b, v, R4 W# o, e
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息9 q8 y* ~, U! [4 i
  96.                             string[] msgList = userMsg.Split('|');. g  f& ?* k& l! {9 ]
  97.                             if (msgList.Length == 2)% H0 t. [0 M; D% s
  98.                             {
    7 d) y+ k5 K9 d- r. D/ z( U, _
  99.                                 if (msgList[0].Trim().Length > 0)
    : l# B! e# U$ d( p  U6 [3 j
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    ; N2 M* `) S$ X) S& _, j
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    " e; Z# g. C  `: r, |" r
  102.                             }0 j) ?9 U3 }  _6 M2 {, c
  103.                             else: Q; b" a& @" ~( o( D0 l
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    1 U6 W/ @4 }! _8 R5 I- V) w
  105. . P& d# `" k! C- W. v% C
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线8 d' Q0 {$ V. T- w5 Q
  107.                             {
    4 g9 t& G: x+ L: }
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端' D* v! G: ?3 c+ [* E/ V% o
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    . A4 I: q- {$ }8 u  ]6 ~% p
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);8 Z, ?" f7 T( }$ V- K: ]
  111.                             }% U! W2 e: R; M( x4 O
  112.                             else1 s$ f( t! P4 o; i) ^
  113.                             {
    $ O# J- Z, E  w  I
  114.                                 Task.Run(() =>+ r. O5 N' Y+ j! @4 R
  115.                                 {
    0 k( I7 L" D7 h* C9 W7 X8 Z
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中+ M3 m4 x/ g/ x# Z! z8 Q2 W! K+ G
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());" ^1 W" u/ i2 h2 @' H
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
      v; h) x0 z: h3 l
  119.                                 });* M; ~% `' ^5 j
  120.                             }
    : W3 z& I* m2 a* |2 z5 X
  121.                         }
    " A. {' g- n7 ]" o$ R+ k# B3 \
  122.                         catch (Exception exs)1 C2 M* `2 j0 B9 s" Y- b. W
  123.                         {7 H! S3 a+ D9 ]" |% i' T
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    * W2 W9 }( r) r6 F
  125.                         }
      y% ?/ W. G& m0 i) Y( X; n- i/ A; B
  126.                         #endregion- f5 o0 t/ f' L( A! e5 g! \" K* Z3 r
  127.                     }5 }: H: k! t# h8 d4 |; A$ a, U
  128.                     else8 \  ^/ M& r- K+ \" O
  129.                     {- F+ }: N( n1 w( i
  130.                         break;: G8 S! u" Y0 z- i0 U2 d2 Y3 |
  131.                     }$ P! d# \! T0 H
  132.                 }//while end
    / k; T$ r+ d" ?$ P
  133.             }
    + V) b; D2 d5 [. W7 \) Z, |
  134.             catch (Exception ex)+ L8 i! j6 A3 l1 ~) m. d
  135.             {
    + b: E. [3 m$ ?. F( H+ m' |
  136.                 //整体异常处理
    * Z1 A3 i# |' ^
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);! x, o! S" }4 N7 @3 s
  138.             }
    / ^$ H$ C' w5 x) o
  139.         }
    5 [* l/ J' M9 @9 @! s$ `
  140. * c: {. y& V$ c+ q( j

  141. # m# M( i1 A6 K
  142.         public bool IsReusable# o6 v( q$ d# O. t/ E7 [+ `: ]
  143.         {
    6 t- H! ~, d% `( M" {( T8 Z+ D
  144.             get
    6 ^4 V& q3 G$ W' ^
  145.             {
    + ?4 O1 k4 [# y1 G
  146.                 return false;( M0 X7 I+ h2 \4 Y: [
  147.             }0 L+ T5 Y- x: t, n3 C/ [7 b
  148.         }0 L; k$ e7 f: X9 m4 I, w
  149.     }, y. ~, b: ]! g; g( P8 r
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

% k- T0 [( P* |+ X




欢迎光临 cncml手绘网 (http://bbs.cncml.com/) Powered by Discuz! X3.2