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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
9 @9 `5 q" t4 w' q1 u! ~
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;  H6 C  `+ s  k; m# e8 W; I
  2. using System.Collections.Generic;( @- d8 _" u% W9 ]* Q; H3 ]
  3. using System.Linq;! E( V# J& h, c7 p  g
  4. using System.Net.WebSockets;7 \6 w0 s0 A' H9 ~
  5. using System.Text;+ i( V: l0 z; j$ T: M8 _
  6. using System.Threading;! A* o  Z5 {( @0 D) Q
  7. using System.Threading.Tasks;
    ! s+ d7 F, {/ u' F9 ?0 Y
  8. using System.Web;
    " @3 B7 o) u* j9 j& v: |7 F9 t0 ]
  9. using System.Web.WebSockets;5 b/ B% y" G! r/ M! T& y: R# Z9 x* }

  10. . e" T" n' ]. `  F1 G% d3 f* e
  11. ( ~+ g) j3 A; m1 d# H
  12. namespace WebApplicationWebsocketHandler
    # b% w5 V5 [! W  V* W
  13. {0 B# r. p$ H. `, g+ A6 o+ G  Z
  14.     /// <summary># T  Z6 P- {3 G3 T5 y
  15.     /// 离线消息6 h, f) @$ F% O6 E  h: L* o
  16.     /// </summary>
    / q) w2 M7 d" d, F- a
  17.     public class MessageInfo, {, b& w! v* O; x
  18.     {
    ' O* T, T  M; M( Y* c
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    : n" O! l! e) W3 n, Y3 C
  20.         {9 ]: Q6 Q2 `7 n2 P: c. U0 ~
  21.             MsgTime = _MsgTime;
    2 ]7 c% G  J5 O
  22.             MsgContent = _MsgContent;# U/ w6 |6 @* N  k
  23.         }
    ( I1 V; p+ @& \$ x2 t- u
  24.         public DateTime MsgTime { get; set; }: u5 z, Q) s1 s. v
  25.         public ArraySegment<byte> MsgContent { get; set; }( J& }8 q  x" V6 e+ H  A
  26.     }
    8 T4 [/ p' b0 S* l+ h+ _/ E

  27. 9 g" B  n* v2 z! O+ A  P

  28. 1 a; ?  Y( a- m5 n1 k9 W

  29. 1 o5 ]( k' U8 t" l
  30. " }& p2 P6 D  n' L. n# h, A. U" B8 q; w
  31.     /// <summary>
      }% q) u& P2 j* N0 V2 ]
  32.     /// Handler1 的摘要说明
    - u4 v. Q& G& p
  33.     /// </summary>
    0 V+ q' A! d) f: t- t$ t5 u) {
  34.     public class Handler1 : IHttpHandler- a, \/ A" _* X: J  L1 e
  35.     {! w. v! Y2 }7 j+ G) t$ [
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
      j7 i* t' I. l: u9 @/ Q5 f
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池6 O3 y5 T, d4 d  G! c6 A% w5 `
  38.         public void ProcessRequest(HttpContext context)
    2 k7 U" P1 H" M' I* H$ l$ s& C
  39.         {3 d# w  G6 W" g; l/ u5 Q
  40.             //context.Response.ContentType = "text/plain";  U7 l# X( C6 J3 J. U
  41.             //context.Response.Write("Hello World");
    7 U6 j; T) ^+ C! j3 l) O6 Y
  42.             if (context.IsWebSocketRequest). a* a! f) \0 \" O( W$ r+ s! Y
  43.             {
    ) u% e$ n5 J* B/ i. f& v$ q0 h
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    1 |0 ~  b! Q2 G* l
  45.             }
    ; ^; N8 g9 U5 \4 E; p! b+ @
  46.         }
    7 n& m9 A# a7 ?" E. i

  47. # o, f. Y* ?- v* H( d+ M# {
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    , U# K8 D' D" g
  49.         {
    5 s% A8 ]# X" W7 B" [6 E$ u
  50.             WebSocket socket = context.WebSocket;
    " G  @: }. m9 ?4 T4 Q
  51.             string user = context.QueryString["user"].ToString();5 K0 m& C" }$ a- J) E; `

  52. , i+ f9 f. w/ T+ |% l, j
  53.             try; i$ d$ m2 q/ l! @7 |. X- t; M* @! c' s
  54.             {
    9 F. j6 s! @; z/ }' l
  55.                 #region 用户添加连接池
    3 H" y# I5 C' [; }
  56.                 //第一次open时,添加到连接池中
    7 ]/ V3 b& p/ ]
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    6 K9 T: ~. b; @% V, _, z  l' {
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    + B+ B. ~' F6 s0 W, P
  59.                 else. F0 U9 B2 z/ o: I8 z+ F
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新2 ]. r4 _8 X. x! Z* E7 }, L, q
  61.                         CONNECT_POOL[user] = socket;
    6 q, ^- N. b8 S2 G7 I) r
  62.                 #endregion, M; T: E, u/ z& M! [

  63. 9 [1 v; {5 f+ N: l% a
  64.                 #region 离线消息处理! R, U1 o( O, \+ ~9 v
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    * r9 a8 k# f* H! x% Z& G# x* b
  66.                 {
    & ?$ `+ x. H  |  z4 U+ c! X9 A
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    * h8 C; @- o& S6 u- X+ t
  68.                     foreach (MessageInfo item in msgs)$ L) d9 g& E8 _5 x9 v
  69.                     {: Q6 R6 i# a# b# v, s1 H/ R* r* A
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    + A# M0 |# a* a. v6 d0 b
  71.                     }
    8 \- Z2 }: W9 \$ K$ o
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    5 {4 N7 [; h0 c3 f5 Q; }, v
  73.                 }- I5 s- @5 b. v
  74.                 #endregion8 o7 D1 A" Q2 t) c9 \
  75. / @: V9 g- |1 k, m+ V& j7 t
  76.                 string descUser = string.Empty;//目的用户
    4 E8 f) P- @: I3 U
  77.                 while (true), [9 ^7 G2 `3 K  c9 X( i
  78.                 {
    5 u1 H$ C7 u. {& [# j
  79.                     if (socket.State == WebSocketState.Open)! a" e# w- V# k- K  n
  80.                     {6 B: k- N# P; }- Z' L
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    & v0 p6 L) F) ?+ }; Q% u$ o9 m- {
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    7 t" k, [7 O% f& _: }

  83. ) Q9 C! d3 V6 {7 ^+ s
  84.                         #region 消息处理(字符截取、消息转发)
    + }: P2 U/ r) P& F" `0 v+ a7 t- s% c
  85.                         try; d; z; P% A: N7 q& W: J. k' X
  86.                         {* X5 b# }" j  O5 z) v# P
  87.                             #region 关闭Socket处理,删除连接池3 y8 g, j4 Y% h; E+ L" x
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    1 R* r# e6 a8 q/ i" n1 H" u* E
  89.                             {! G8 L  }( I; D# S2 H
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    , S7 {9 S* z/ u: D3 F
  91.                                 break;; ^- [# `& o- I$ O
  92.                             }  {& R: ]( C6 C# x: a8 C9 }
  93.                             #endregion; L$ n; g5 ~1 ?7 O9 J
  94. ( s  [& E0 q' g
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    , w, D+ u5 j$ x3 c4 k+ _' ^
  96.                             string[] msgList = userMsg.Split('|');
    ! K1 `* d+ o) |/ l" G& q$ f) Q
  97.                             if (msgList.Length == 2)
    ) v/ k" I+ s' L' B5 Z
  98.                             {; H( ~  h) V  i1 T2 U5 x3 l
  99.                                 if (msgList[0].Trim().Length > 0)  [. b1 H$ I9 E$ q# K
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户, q9 P0 g' B! o4 U2 u- s
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    2 t- o% ?& W  F# Z' N3 A6 L4 T9 p+ V
  102.                             }
    $ {7 t3 a6 Y9 u
  103.                             else
    , ^& o4 ]4 J& Q5 J: c
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));0 K+ c) r* ~3 G4 h, W; I3 v
  105. ( J% R5 n3 a7 R1 j; V
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    + \& M. J  {0 d# F
  107.                             {1 C& v: w3 B) ~* R
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端' M4 e5 \2 I+ b  m# O
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
      @0 H* u; C: v* P3 _
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);+ U. l/ L4 F8 q( E
  111.                             }
    " D5 P* G/ x$ I, v
  112.                             else1 H* v( W' @  Z: U# }  g$ Z
  113.                             {
    . o& B% _+ J3 k# i% Y3 @
  114.                                 Task.Run(() =>
    : ^! U6 G) W; c: N. y5 X4 j
  115.                                 {( |! H' J9 i) }/ ^% K# R; B
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    1 l! ~: q# Z8 @+ }7 j
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());8 g8 n$ [) n9 n( u# N6 K9 ]8 u
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    5 I! f- m, k' i8 h  Q7 l1 i3 F
  119.                                 });6 m/ M% ~0 D9 ]$ U) R2 V
  120.                             }
    0 ~( r' h9 ]$ P" S( q) W
  121.                         }) ]; \- Y  E! u; V+ a. P' x
  122.                         catch (Exception exs)
    / x5 C6 _! |: ]( P
  123.                         {
    1 _- g: f$ o8 B: L
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    0 E& f: l9 O& {! B0 {
  125.                         }; N  ]6 d% d* k8 h+ J( O
  126.                         #endregion: j! N1 E- z, R: ]
  127.                     }
    + r( ^. q- s9 P  @: s- ^7 A  w
  128.                     else# P, r2 \2 i1 o6 \/ q& I5 y
  129.                     {
    7 ^" r4 a+ _# B  I* D! [+ |
  130.                         break;
    ! `2 b& {2 U9 g7 i" `- H
  131.                     }
    5 a8 ^  u, t5 P# r* x; L3 q
  132.                 }//while end7 M8 c3 ]; _* }7 u4 ^: c" r4 R
  133.             }6 o) _  O8 u, f' Q
  134.             catch (Exception ex)
    $ d' N; S) o- X! T4 ?
  135.             {. N( \* ~. G( a$ b5 w/ c* r* ]
  136.                 //整体异常处理+ |& k) ?6 k9 [3 P( N. W3 {6 Q, l8 I: E
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);" ]8 }7 T. [& J8 [
  138.             }
    1 A& X; L9 S* C( T2 ?
  139.         }1 ]- D2 V: M7 a. P$ U  P# ^/ g4 E

  140. $ O: V$ K1 Y% E9 U2 Y6 D
  141. 1 U* F# C, c2 k& }
  142.         public bool IsReusable
    . d; }& U; e5 V4 H. P
  143.         {6 {+ E2 ]( J- r) Y; g3 \/ n
  144.             get
    & _$ r( ~) |, B8 z
  145.             {- |  H/ D, L+ L  L
  146.                 return false;
    ! z  y6 i4 m; w. U% l4 w1 j
  147.             }
    # ^% d: f' }. K& N" E$ h  c& ~
  148.         }" o2 Z: ?. j8 s8 ^8 O. o) Q% _
  149.     }, N7 {9 M- X/ z' @; a- d4 G
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
7 u. v9 s- O2 i  f5 b
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-20 20:09 , Processed in 0.135159 second(s), 25 queries .

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