cncml手绘网

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

作者: admin    时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
, K# T% a+ L' n
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    6 l; ?8 c/ n) e& C. \; \  F
  2. using System.Collections.Generic;: E; y( a, V$ C% E: f+ U/ w( W' D* G
  3. using System.Linq;& n' z. A6 v+ @9 C% C
  4. using System.Net.WebSockets;
    " D  f+ ]! @2 L% j: b3 `8 d
  5. using System.Text;! \: ~- ]" W1 M4 ]# \9 I$ J. W8 B
  6. using System.Threading;& K& i7 V9 @& F6 I+ g# y, H* ^
  7. using System.Threading.Tasks;- P# N: U! v$ ?, b4 _
  8. using System.Web;2 K  E1 H. v4 `% F7 P4 y0 `- B1 v
  9. using System.Web.WebSockets;
    9 y% Z  r, U2 P

  10. . O* V, E% e; d6 P8 A: j  R6 T5 q

  11. 6 h* f6 g* s% v) {9 N
  12. namespace WebApplicationWebsocketHandler
    3 `" S% d' b! I+ i; V* f
  13. {1 ~! L; P& u# W) e$ r
  14.     /// <summary>" ~  l( S* T7 p0 o  K1 E, C/ w* D
  15.     /// 离线消息% d4 m) H' W; f& n+ ^8 e6 L
  16.     /// </summary>8 Z6 |7 J) D% {% Z4 H1 H
  17.     public class MessageInfo* H# F: t( v4 Q
  18.     {
      ^* R1 H7 u, H! g  L- m
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    ( \: Q+ L/ ^* ?9 k$ Z+ z; F6 v
  20.         {% ~' Z+ R+ Y% `( s
  21.             MsgTime = _MsgTime;3 i' X+ g  g! T; M- \; `
  22.             MsgContent = _MsgContent;
    ) J4 G" `7 Z& y5 g& j  E- ]+ D
  23.         }
    , d! x8 X7 i; g1 \
  24.         public DateTime MsgTime { get; set; }1 L- _) ]* K  |6 @4 N
  25.         public ArraySegment<byte> MsgContent { get; set; }
    , |% @6 h- B- H* D/ H/ u
  26.     }
    ( O3 e7 S2 M! A
  27. ! H# y! S7 t+ _6 ]" ~

  28. & a/ B  N  K6 n+ [# ~7 C
  29. 5 k+ O% _2 s/ U6 I

  30. ! m  u0 [6 R1 F/ l( \5 }
  31.     /// <summary>
    6 H5 K6 t9 e. ~9 i7 B
  32.     /// Handler1 的摘要说明
    - ~9 ^# z1 o0 v5 Q
  33.     /// </summary>9 l8 ^! z2 m4 }0 M7 G2 h
  34.     public class Handler1 : IHttpHandler' i% q. c* t' |% R% g( ^4 L
  35.     {
    % |9 z* E' N  v9 T
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    5 u% \0 P) {4 O5 W% D5 z
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池3 B0 H- Y8 I8 g" _0 I; N
  38.         public void ProcessRequest(HttpContext context)% w) b9 O1 V. v
  39.         {8 T' i& w# B+ C* o- v
  40.             //context.Response.ContentType = "text/plain";
    : c( Q" t, a! e' J1 E6 Z: G0 _% q
  41.             //context.Response.Write("Hello World");' `) ], T5 h0 [9 G
  42.             if (context.IsWebSocketRequest)& {) n4 s* l, T
  43.             {1 L7 Q) t7 a' Z+ Y: b( P
  44.                 context.AcceptWebSocketRequest(ProcessChat);9 ?* S7 }' ]3 I2 q3 s2 o  E
  45.             } - O. u8 e: H8 m/ ]9 S/ N# f
  46.         }
    + j" ~4 \. C- E. A/ q6 W
  47. 7 X& ~) B) O1 S1 {4 ^8 |7 J
  48.         private async Task ProcessChat(AspNetWebSocketContext context); \2 _; ?9 q# y" @! s: I
  49.         {) h$ f; y5 j+ D  T' e% k
  50.             WebSocket socket = context.WebSocket;+ L" H0 j$ h/ v- t; O" |
  51.             string user = context.QueryString["user"].ToString();
    2 s1 i" c) j! {& n. ]- B2 ]

  52. ' _; U8 d1 X- R6 P! S8 H0 c$ S# I
  53.             try; k6 K# V* l5 T. o. U; m$ m; B
  54.             {
    . q* q/ K3 `+ a6 k; W- x: P& f
  55.                 #region 用户添加连接池* t) N  e% e0 q  G2 K1 X
  56.                 //第一次open时,添加到连接池中
    0 i7 }) o# O( Z  S  E% o% d6 M
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    0 w( |9 u/ P. L5 q1 D* a
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    : }: ~. o& P" f3 _( B0 S
  59.                 else7 H  p1 g' R' I
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    . \- e& u; F) G
  61.                         CONNECT_POOL[user] = socket;& I7 E. H# k' h' ]# d! q4 s: ^) c
  62.                 #endregion; `5 P! I' |9 z" }
  63. * m$ C% i- E/ n2 A, S  X
  64.                 #region 离线消息处理+ ?3 k+ t  G, L( T2 d( I8 Z
  65.                 if (MESSAGE_POOL.ContainsKey(user))4 D$ o( b& a- D5 [1 ^8 B8 j
  66.                 {
    ) k7 l/ B6 t6 X; l, E& [
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];! j; i( K4 y6 K) p7 @' g
  68.                     foreach (MessageInfo item in msgs)
    5 {. ^8 z& F0 t5 d
  69.                     {
    ( A9 p0 |' Q- G4 B* F
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ( S2 ~* B2 F% V' c
  71.                     }' j; s9 i0 z2 x$ H5 \2 g
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息6 v7 e8 c0 F$ I2 u5 P, T
  73.                 }& D$ y( C. L; v. a) E) b
  74.                 #endregion
    % ~$ s% V6 t. x1 J1 D% M5 }: ]
  75. 1 a& a$ c( w  m$ u3 P  L2 c/ [
  76.                 string descUser = string.Empty;//目的用户
    $ S5 `0 T8 i# W
  77.                 while (true)0 R4 x. G' {: c+ k. ~2 w
  78.                 {
    0 V6 O9 N8 b( Q# Z, u4 X
  79.                     if (socket.State == WebSocketState.Open)
    3 B3 d* @8 \4 w' a9 q: l
  80.                     {
    ! m3 {8 A8 G% p
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    2 g% Z8 ]$ m* @" t3 Y) x: c
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);8 U6 n, @# x. z4 G/ I

  83. % u3 W$ v8 h5 P1 E
  84.                         #region 消息处理(字符截取、消息转发). E2 m& u% I% |+ K, t
  85.                         try
    7 a" j5 l! b5 `
  86.                         {0 ]" z# s: u% e0 Y7 f- a9 r7 w
  87.                             #region 关闭Socket处理,删除连接池
    ! L# m  Q" |5 L) C- V$ V
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    9 K6 Z+ {$ Z0 Y! I9 g( y: M
  89.                             {  b+ X' a$ x1 K6 R4 @+ d" @- N
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池( U8 [0 b/ A9 [; i8 w- Y
  91.                                 break;
    " K* g+ B# |% s9 y, l3 U/ }+ v
  92.                             }* l! X4 i; w" w" O/ a* u
  93.                             #endregion% d1 K- H6 v3 x; |- G$ W. s

  94. & [% T$ V" ]6 w# h/ \
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    7 b. o2 b+ ?& @" y' i4 z
  96.                             string[] msgList = userMsg.Split('|');6 A; i5 k( ~: F0 X4 U! I  u3 _( j
  97.                             if (msgList.Length == 2)
    1 E, ^3 k1 a0 _% n( _/ j
  98.                             {
    ) X8 s* [5 j' x: P) U. c
  99.                                 if (msgList[0].Trim().Length > 0)
    * E: K+ {4 i7 d) _" Y0 h
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户1 }. {) R, T- ]. F
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));( Q, _- h3 X% X; ^- V
  102.                             }/ O9 `  _8 ?* r; ?3 t
  103.                             else: y/ T% L( h9 U* c
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));- H3 X- k4 t' S: D
  105. 2 R& G$ o8 @9 c( s4 z/ z
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    7 }) v8 S$ Z7 `. \$ n/ ]
  107.                             {
    " y  Q) h% I4 U6 S: ]4 \
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    6 N$ f! q+ X5 A$ M) M9 B5 O' B
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)4 e2 E9 |; e$ q( {
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);5 `8 e$ l; I: q
  111.                             }$ i3 N+ k2 {! a! G! }- `- S0 g9 Z5 Y
  112.                             else
    1 S5 n& @2 o: d- T; \0 A* Y
  113.                             {
    3 k" ~! T6 U! r- F( E  x" a
  114.                                 Task.Run(() =>- K4 i5 t! Z! E& w* N3 |# `6 m2 X
  115.                                 {
    9 l' l  n9 [1 w" c4 F- {$ U; Z& I
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    / S6 `% ?! {# g$ h' Q
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    $ n3 J; j  W1 M# L: ~. h, V$ v
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ( E& E  P1 S! u# |$ r0 \1 p
  119.                                 });
    2 `; N3 i, ?/ c; _
  120.                             }. A! Z* ^# v! g8 o: `1 \, V
  121.                         }  a/ Y$ P* V! e8 B
  122.                         catch (Exception exs)
    , B5 T3 F) ~. e2 i# |0 A- A
  123.                         {
      \" P: c+ L7 A
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息! o2 {% P2 h( g/ M
  125.                         }/ ^" [" F) `! l$ y
  126.                         #endregion  K/ s6 \# _  Y- N
  127.                     }5 U$ e3 G) [+ [) o
  128.                     else! f" ?* |! v% j! o
  129.                     {9 a0 c! D% _" g" s4 C* |6 e
  130.                         break;3 R  Q. t, Z6 T8 F2 E3 W# b2 I
  131.                     }8 a2 k! g4 h, f' M4 P! ^
  132.                 }//while end# _  {- u. W0 u+ E6 P' C  _8 L
  133.             }
    & ?2 W) b0 m1 z
  134.             catch (Exception ex)' M5 |4 W, d& u( T% [) N  S( ?
  135.             {
    ' i% r7 ~5 x8 m- [, ^$ U) u* A2 V
  136.                 //整体异常处理
    ' C) [! m& |! G  ]4 l1 G
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);2 v; O! m8 L$ Z7 H: ~
  138.             }
    ) [5 t2 J# U. x
  139.         }
    9 Z* e: E9 R8 T

  140. ( D0 t  s" p9 ?0 x: G# j% D+ V. }

  141. 4 P) u, r7 p- K8 E
  142.         public bool IsReusable9 S; e2 [6 D# T% f+ R- t2 @/ C
  143.         {  e; |5 i( p3 O9 ?6 Y
  144.             get
    8 e* e* n) U  q% u0 ]
  145.             {
    ' z3 M( o, N" K2 X& A9 t) r
  146.                 return false;
    8 t7 c: u' ]3 E. z  E4 R  p4 M
  147.             }2 i2 W  p, C* s- d7 n9 w: |4 q
  148.         }5 Z% X$ _6 M4 o7 a4 w2 S) O- K
  149.     }
    0 f1 L$ H  \1 r
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
0 Y8 S, h* u5 u" z





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