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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

* e" a( c7 c' n/ ?. q
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;4 V6 l3 j: X2 y+ d. A# o
  2. using System.Collections.Generic;
    4 C: D# i( k; F9 f
  3. using System.Linq;
    ( s) C' k0 H/ B. q" K
  4. using System.Net.WebSockets;
    & `7 u0 q, }# M0 V: z  J0 [& C' [. S+ h
  5. using System.Text;. J. ?/ V. }6 H6 \5 X
  6. using System.Threading;% H6 M# c0 v$ V% z1 r
  7. using System.Threading.Tasks;; V$ ]: R2 F! R8 i: {; ~
  8. using System.Web;
    8 h$ i9 _. \* Z6 D7 K+ @) @+ G
  9. using System.Web.WebSockets;
      O* c* t& o. m
  10. " O: f1 {' n  A, I* p

  11. $ q2 F% m7 w4 n' `% x' d0 h; ]
  12. namespace WebApplicationWebsocketHandler
    2 t& u2 f5 S. n' f. O
  13. {
    2 I$ T$ l; U1 E+ ?
  14.     /// <summary>
    , S- C2 \1 V  ?- d: V( r# o
  15.     /// 离线消息
    . m- A: B% \& U3 c5 s; D
  16.     /// </summary>  c: O  h  x8 r! ^  P0 [. B
  17.     public class MessageInfo2 f$ H6 X. r8 H$ V
  18.     {$ f* h1 y8 p, H6 m" ~+ B
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)7 {2 j$ R; x2 U# ^; M. e
  20.         {1 v0 p' I* C, `9 v5 X% D
  21.             MsgTime = _MsgTime;
    . z1 z( B5 ]& R: o5 Q: c" N
  22.             MsgContent = _MsgContent;1 V8 k/ Z- j. F9 S8 d& E
  23.         }$ r+ _1 A) J5 I: s. p6 ~* G# x
  24.         public DateTime MsgTime { get; set; }. h9 f% l) r7 n4 v7 }- ~9 d
  25.         public ArraySegment<byte> MsgContent { get; set; }
    + F- J. T0 v7 B3 ~* I" a: j& y; n; L* y
  26.     }0 E! C0 a* O; S8 W

  27. + x4 ?  Z" M# w+ ?( I6 n
  28. ' c7 b% U3 ^7 a# x& Q+ m( v! R

  29. - p+ _2 u1 Z3 Z& s

  30. ( _3 y* Q( w" D4 Y, T: C# O0 c
  31.     /// <summary>3 m6 U- o+ j4 |  f1 M$ b
  32.     /// Handler1 的摘要说明: y/ T! x. D3 }; g4 h) m
  33.     /// </summary>' A& [( j( x. F7 l3 w
  34.     public class Handler1 : IHttpHandler' H* Z* [+ ?% h. N2 _# p3 V
  35.     {
    0 H/ |+ j9 d+ {+ d$ W- W7 B
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池2 X6 @) y) g, F
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    3 x( c" L# t1 c6 h, {
  38.         public void ProcessRequest(HttpContext context)
    , i% t7 R9 a- V" t7 n
  39.         {
    - P( ^, b3 Y  ?& H9 C
  40.             //context.Response.ContentType = "text/plain";2 _5 t  J) a) X: s. h8 X
  41.             //context.Response.Write("Hello World");
    8 j1 r/ o6 B' L! n; x( W. K
  42.             if (context.IsWebSocketRequest)
    , X8 Q0 X1 c, J
  43.             {& |1 E$ j  |% r1 s6 l
  44.                 context.AcceptWebSocketRequest(ProcessChat);! \* X" D' Q; t
  45.             }
    $ m; w9 _, r7 J( G
  46.         }/ `  C$ ]4 ?- O+ w

  47. 4 Z$ C; `2 r; h. ?8 [5 {
  48.         private async Task ProcessChat(AspNetWebSocketContext context)# |& o3 T0 A( y7 o* t. I) `9 E
  49.         {# U" D, x8 }# {, J* R% w, T3 l- `
  50.             WebSocket socket = context.WebSocket;4 d+ ?$ n$ g* U
  51.             string user = context.QueryString["user"].ToString();
    6 X5 N/ Q: B  P1 Y/ x, [# w. e! L

  52. 2 P7 c0 R* q; g; F# A, S
  53.             try
    ( o. t) n8 k5 o
  54.             {
    + b' p7 f/ w) Z1 @. a- t/ T7 r
  55.                 #region 用户添加连接池2 _3 W2 w, l( H; M5 g& r4 y9 V
  56.                 //第一次open时,添加到连接池中3 W9 d3 [  @! {2 r3 ?
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    ' b+ X8 r' a+ K
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ; K& K, j% t. S2 ~. {9 c% d
  59.                 else8 h9 B+ I, d5 E- q
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新) @* O( b: F1 m& Y
  61.                         CONNECT_POOL[user] = socket;1 \# s6 ^& i  o$ j. [& W1 c9 J
  62.                 #endregion5 v& c9 \7 ]( H. k# O, J4 _
  63. & Z: q+ w% ]/ ~
  64.                 #region 离线消息处理! s4 o) \, H: A, V
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ; b4 A* f# v* b, X5 R- v% z, ?
  66.                 {! ^, I. x+ d( Y4 D+ f
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    2 u- p! H* t; h
  68.                     foreach (MessageInfo item in msgs)
    , C1 x- u8 f7 o5 P
  69.                     {
      ^3 \( b; y! h- g  |7 c' E# t4 @
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);/ T! E7 R  e' |& g7 K( @  b
  71.                     }
    ; A9 Y3 V$ U4 W2 A
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    , [8 n9 d; b; j, w! |6 `5 X: u- Z
  73.                 }
    / h8 G- h' }6 K7 N* {' z1 V
  74.                 #endregion
    % |, t: U2 B& U' x
  75. 0 T- p3 `5 d0 ?$ W8 `5 |& l+ T
  76.                 string descUser = string.Empty;//目的用户+ b+ V- [. N3 \3 r# `8 [9 p
  77.                 while (true)4 m7 C* L" m. W* P  H0 w
  78.                 {
    % W( Y7 e$ Z* l& T! c$ i
  79.                     if (socket.State == WebSocketState.Open)
    , V- k* s0 Z+ ~3 |
  80.                     {) }4 }% J( g5 b4 T, _
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);# M+ V& P8 n- _/ j# U
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    , C- Y  B1 N2 T3 ?2 P, ^0 C
  83. 4 K, O! }, H) C. F3 S8 ^3 }0 Y& u
  84.                         #region 消息处理(字符截取、消息转发)9 D* v8 v- a- w" }, c: J
  85.                         try
    " R, i6 m+ \7 h7 G' E/ l
  86.                         {
    9 |- _  v1 P# a3 q
  87.                             #region 关闭Socket处理,删除连接池
    ( l" R% f0 W# H1 a- |% {% `
  88.                             if (socket.State != WebSocketState.Open)//连接关闭4 j( p, }1 O; I8 s6 B
  89.                             {$ D. i/ p. w! e9 F0 G8 V5 c- u( o
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    ; P8 O# W5 a, T/ L& m" G3 R; @
  91.                                 break;% A, L0 {( h7 W7 A" |$ m
  92.                             }) I  |* ^1 P* I: p6 I& r+ `7 L
  93.                             #endregion1 B+ x8 F2 F6 o  B
  94.   u% F1 k5 Q( u7 r5 @
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    ) X- c1 I; m8 D3 [7 X* H1 n+ W
  96.                             string[] msgList = userMsg.Split('|');9 ^/ c3 e# d% I
  97.                             if (msgList.Length == 2)
    * M; v2 Q1 b1 `# n+ h- b
  98.                             {7 \# M2 z! [! p+ D7 F8 b" S
  99.                                 if (msgList[0].Trim().Length > 0)
    / w7 z/ [, ^1 p, |, Y7 l
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    6 b" t  v1 n$ g8 a9 ^; b
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    ; a0 f7 _( m7 A* Y1 e
  102.                             }
    ; S* b1 x: ]1 Z4 J, c
  103.                             else
    1 W$ \6 E+ n0 x4 e! V
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ; O( A7 y/ ?( {! o
  105. / T0 R$ M" b+ R& q: _
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线! n) |& x( e0 T
  107.                             {0 W- L) t7 M2 N" A: M' e" e. C3 V
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    5 t* a* }. I7 G1 d9 |- X& a7 p
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)/ m8 m; Y" x% L. l" R, k( v7 A
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);" D7 n  h- S& h3 g' M  R% v$ \
  111.                             }9 r* ]$ x- D% s1 U0 P- |
  112.                             else/ T, I5 o& H, P2 Y, f
  113.                             {
    3 O" C  S9 m9 A6 E7 f) ~9 K
  114.                                 Task.Run(() =>. ]/ ^: T+ d& m3 g, n5 [4 y
  115.                                 {
    # }4 h1 r3 k; ]7 |  q5 x
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    4 i; Y( o) n. z
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());% s8 e6 t) y8 b2 s4 \7 t0 R4 m
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息$ D& t1 Z* n/ L
  119.                                 });
    5 V9 [' R$ V# |/ G* v9 r
  120.                             }  z. z; \. G; z  _/ j
  121.                         }6 s+ x( V5 J0 k0 \* p9 U) y
  122.                         catch (Exception exs)3 r) g: J3 p3 C
  123.                         {
    + n5 T1 y" Z$ L2 o
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
      [0 u4 S0 d% R0 c0 `
  125.                         }
    & w8 u! W9 u# ]0 i5 X" n
  126.                         #endregion; g; n, }# n) S5 f& O" J
  127.                     }
      e, g8 U/ Z* C3 z( G  y  ?) b# O: k$ \
  128.                     else
    ; W8 f6 C- b% u  N
  129.                     {
    - t1 _* T' D- p
  130.                         break;  u! T+ G+ D4 ]
  131.                     }8 c& J; b( E7 c* M
  132.                 }//while end
    % D! D5 ?5 L: u. ?' W7 x
  133.             }5 O% e% B; @: M* {) j9 E, p
  134.             catch (Exception ex)
    # b5 U9 v4 \/ F- J8 }
  135.             {" G! ?& V5 G0 `; h$ X3 N
  136.                 //整体异常处理
    0 J$ G% I1 o7 J  P! O5 B' a
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    . C% G! A' ~( J7 ^
  138.             }
    0 \$ ?8 M& k- ~, U2 ~3 z- n
  139.         }2 Y4 v. O. W) X5 w- f

  140. : u; N8 z! L+ E( U
  141. * {9 b4 d" [# Y
  142.         public bool IsReusable
    1 l6 N8 C# q) w6 |. z9 z5 w
  143.         {
    ) [: U+ S5 m: X5 Y
  144.             get8 q7 g4 T* }8 g5 y3 U' g3 t5 e
  145.             {
    0 f: S- V0 g8 Y% a
  146.                 return false;$ y# B( @/ |1 p2 c6 }4 Y
  147.             }0 m% Q0 c$ `8 j3 l0 V
  148.         }, H! Q9 M0 I( u4 n" a! u& j9 _' J
  149.     }1 S/ H0 r/ T0 L3 M! w9 {
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
0 z3 ]1 Y) R2 s6 \  U' f
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-4 16:42 , Processed in 0.072742 second(s), 24 queries .

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