cncml手绘网

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

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

0 O4 l& a; Q6 d
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    6 G3 ^7 k% t- G- i
  2. using System.Collections.Generic;
    ) g) n& m/ E7 j7 O" J% c
  3. using System.Linq;
    9 r8 k. D# O+ ~( E% \
  4. using System.Net.WebSockets;5 l! j- {9 g4 P5 G& L- G7 N
  5. using System.Text;
    ) U: T; i7 E- B) d
  6. using System.Threading;
    7 O  _8 E% y; x/ Q) u
  7. using System.Threading.Tasks;6 R& F) M* k5 f1 Y
  8. using System.Web;
    ! N' }" ?+ g4 p7 \( `% P% E' \
  9. using System.Web.WebSockets;
    ' k' ^- Y& q' x) M! W- K+ \

  10. # Y) @8 `2 I5 o

  11. ! U+ q! J- b& `# y
  12. namespace WebApplicationWebsocketHandler
    3 i2 q0 T/ R& a: l
  13. {
    $ d! R$ j& W' y& K
  14.     /// <summary>
    # b. j9 c7 O! c( N) v1 r1 x
  15.     /// 离线消息* [7 _# O, ]# g/ r2 D& w0 x
  16.     /// </summary>0 D; B$ h: M9 ?, w' @' n, X
  17.     public class MessageInfo3 t! j- I, h4 b8 N
  18.     {
      H% P/ g. }7 o- v; k/ g7 \6 ~
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    9 @6 s( b/ R6 D- X( d  W# t" L8 w
  20.         {
    1 h5 X2 E; t; X6 q; ~' @
  21.             MsgTime = _MsgTime;
    # C+ \5 f; ~% w
  22.             MsgContent = _MsgContent;9 _: a$ Z$ E% v- q2 a
  23.         }2 n9 p' u6 o+ W4 j8 W
  24.         public DateTime MsgTime { get; set; }+ H& Q6 M3 _$ a  D7 }& p6 I' ]
  25.         public ArraySegment<byte> MsgContent { get; set; }- O# k) y4 Y, m4 w' U
  26.     }  H, @; O1 q7 k$ c5 z4 a+ A
  27. 5 l5 H' P' y; @& ?
  28. " p; F. f; k1 R  K9 L) ^

  29. . J5 H$ t. ?- I# k7 n
  30. . n& h) `9 K1 d# ]6 i7 g, G
  31.     /// <summary>
    6 M! v  B8 m- K. j, l
  32.     /// Handler1 的摘要说明7 a3 H. ]6 g4 V0 p, t; C; z
  33.     /// </summary>: z5 E5 x: W6 ~* `" Z
  34.     public class Handler1 : IHttpHandler
    ( ~$ ?( S8 p2 G0 L/ x: P7 @
  35.     {
    . g. r; Y. U+ K1 L1 F) C4 S# [/ |7 v% q
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    * a( s" h, Y9 J  I3 G/ L0 ]5 S, X9 M
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    7 a& q" m( T1 M  L! g. i
  38.         public void ProcessRequest(HttpContext context)
    3 |6 Y& |3 v- N/ `
  39.         {
    0 I' `: @2 @: X5 M  x
  40.             //context.Response.ContentType = "text/plain";
    * O5 v, W1 n% x: A1 y1 c
  41.             //context.Response.Write("Hello World");
    4 Y& j3 }% H5 |9 m7 ]
  42.             if (context.IsWebSocketRequest)) f8 M$ Q0 h) R( j* y
  43.             {
    5 j9 m: {0 T) v5 H8 X/ u3 f
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    " E; t. u) K# W2 R( a
  45.             }
    : \# n) b) R* b: r  X6 U+ g
  46.         }8 U& R2 @! i% b& V9 Q+ ?" T, |4 j

  47. $ d* [  N: K+ d+ p
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    2 }5 T5 n5 o1 G
  49.         {; `) {/ z/ i7 H& u2 g
  50.             WebSocket socket = context.WebSocket;+ g, V% F4 p2 ?! N
  51.             string user = context.QueryString["user"].ToString();
    ( P, U! b% ?5 W. R

  52. 0 }, ^( ^( H7 L! t7 h) [
  53.             try. ?. g* e/ }( g5 m0 I- C# t
  54.             {
    0 ~( `* v# b7 t1 H5 e4 M
  55.                 #region 用户添加连接池
    , b* d6 M: z! }7 H* K& A
  56.                 //第一次open时,添加到连接池中
    * O) i; p8 v5 O& _- Y8 j
  57.                 if (!CONNECT_POOL.ContainsKey(user))" c3 q' v: H. f/ c! \# d
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    7 G7 ~6 A$ h% C' C
  59.                 else
      D# v, q4 i$ e% O
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新8 D: _4 O7 Z! u, f4 J' Z
  61.                         CONNECT_POOL[user] = socket;* S; O! W( U* t: ^" t; L
  62.                 #endregion. E& h3 `3 W9 R0 m/ H2 V& A
  63. , D! M5 u$ Z! H% _3 W5 O8 Y# I9 Q
  64.                 #region 离线消息处理' z! T  }  h: m1 r2 l4 y9 m$ I
  65.                 if (MESSAGE_POOL.ContainsKey(user))2 f9 l# U( l3 c0 w  P& T* T
  66.                 {5 k& q. q5 p' w0 w5 b- u
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];7 ?5 w4 D8 e: p* ~0 y
  68.                     foreach (MessageInfo item in msgs)
    : D* B# H5 y2 u/ K+ o% A: P9 G6 U
  69.                     {7 b! I0 a/ N1 i* R4 f( j9 w+ E4 ^
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    . j# m7 [9 g/ A5 ]
  71.                     }
    * R! D9 d' c) D
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    + b  X. I: @5 K$ ^' t0 g1 ^+ _
  73.                 }
      @, u7 j0 ?- ]. y
  74.                 #endregion
    / E3 c& d' z$ G: l) [: r1 u

  75. 3 w  d* ~* g* k" s8 u. \
  76.                 string descUser = string.Empty;//目的用户
    ( I$ w& {+ ~/ I
  77.                 while (true)
    $ b) q, h2 U9 l
  78.                 {- ^+ j7 z+ F" K' D7 _4 k
  79.                     if (socket.State == WebSocketState.Open)4 S. f/ v# g" ^
  80.                     {) M8 t5 x* C. n/ ^. p
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);5 K# ?" d6 g8 K# t4 A
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);6 G# U6 f4 R7 E, d! X: E* S) R

  83. 0 I5 w# I8 P  Y# ?; ^
  84.                         #region 消息处理(字符截取、消息转发)% t; Z4 a  W2 [# d1 K6 J
  85.                         try
    " e5 B! W& N# W' [8 D6 H+ r
  86.                         {$ s+ Q4 X. Z) I! E1 a1 `
  87.                             #region 关闭Socket处理,删除连接池$ J) @3 Y  m0 a# j# ~9 i0 P
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ' O: u  x4 ^" K: S
  89.                             {
    4 N3 k4 l6 G0 A+ R5 B! K+ g
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池1 O( D- U) W2 R$ r0 k# N6 c
  91.                                 break;
    5 n! {: i# W& s1 N  O& u
  92.                             }
    % \( ], }" k* ?5 i- n" d' {# B6 p9 Q
  93.                             #endregion
    2 A8 p' r9 D, l! R8 ~1 q' L

  94. " |5 O* m1 A' r1 u# w  C
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息; v0 V8 T+ j- D' B
  96.                             string[] msgList = userMsg.Split('|');
    * W8 I! {  s* ?; ]
  97.                             if (msgList.Length == 2)& P: [8 P, l8 l& ~) J$ O
  98.                             {
    ; }5 R- L! y3 r; Y7 h9 C/ e- w
  99.                                 if (msgList[0].Trim().Length > 0)8 i6 m0 K  R) [0 I% |9 [
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户% b. D2 L% Z" m7 t) h
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    3 _6 u- |% b" P# [& ^
  102.                             }. b+ m8 N- c) a
  103.                             else/ |' w6 ~% _8 ]3 `
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));1 `0 {! F# e  s/ [. Q) _
  105. 3 F/ @, K' D. f, ~
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线8 K% L1 s5 j; A6 s: O! _7 _& j) d
  107.                             {
    9 y# l9 d' O' r
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端* \" T* X  |4 ^
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    7 O& z4 A3 y$ Y: d
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);0 P! t1 X& ]5 P+ @
  111.                             }4 ~' u7 C& u5 e. R' x2 Q  G, {) _: m1 G
  112.                             else! _& h/ s, c, q% V# F
  113.                             {& D& N0 U- o7 F* F* `9 \
  114.                                 Task.Run(() =>* o7 @% g& [6 A* v6 h* `7 u) Q% ?
  115.                                 {
    : }( z( ]6 A: `9 m
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中& [# }; P4 K7 p- g- a- u' _! ^
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    0 G- ]% N) T9 G* R9 \; f
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    # [; C- F3 K9 J; ?. D6 c% B
  119.                                 });# W3 k$ \& K& W9 r
  120.                             }
    - A) `& }2 |8 p- v& j$ j# \% A6 L
  121.                         }
    7 G9 Q. i5 k( J. W/ R1 I) x% |
  122.                         catch (Exception exs)
    % y! }- L/ U" i- |" {4 D0 S9 F8 p) v' C
  123.                         {
    " U) Y4 V0 p, Y
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息5 q. b( r+ u0 I# U0 y6 {
  125.                         }
    3 f8 R+ H! z( b4 C4 y7 I
  126.                         #endregion
    ' M, v  [6 J3 C1 A9 T1 T/ K* A  v
  127.                     }1 ~$ i/ q0 w" X
  128.                     else
    + y0 s/ ^) i7 e# }# `. n; k  r8 E
  129.                     {! }( n+ {% G, O7 x9 t+ Z
  130.                         break;- l- T. d) V# n3 j
  131.                     }( K9 R# R/ |7 S5 X9 i- h
  132.                 }//while end
    4 o$ d% I' D8 u
  133.             }
    " ]' \) @( |/ D. L9 l, V% Q
  134.             catch (Exception ex)+ Q" ?( y, e  @0 ?5 Q  ^
  135.             {0 W" E: a$ y7 ], J0 _# W0 I# V
  136.                 //整体异常处理
    $ |, V& u: N* B3 _$ U4 Y" _4 c% t3 m
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);1 R9 V4 G/ Z0 n  S2 }8 B
  138.             }
    & S" t# V  }6 n, u  J$ e
  139.         }9 z6 t' r4 q) _- ^( C1 {; V; B/ l

  140. ; x8 i" q1 {$ a/ ]8 g

  141. 5 F2 v3 e8 n1 @9 g
  142.         public bool IsReusable& `- S$ o* S2 Y* J- b8 L. I5 r
  143.         {; A% Z" X) f/ h% Z. ^) N" t& R
  144.             get0 c/ J4 v9 Q; `+ A/ ~
  145.             {
    6 C* W/ f6 A8 H
  146.                 return false;% o- `, Y; w$ T: c3 ~: _. a
  147.             }
    - T, _$ ]/ E4 i
  148.         }4 ~: @  l1 [; L9 V. f" x, w  G
  149.     }
    5 L$ F/ m& [- c" K: h
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

7 h& E9 l7 T+ U) E4 R0 j




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