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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

/ [8 O# L* B- V( z0 z" i
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;& x* T4 N$ r' _' b
  2. using System.Collections.Generic;
    0 ~! U6 e: x/ t3 \7 h% R9 P
  3. using System.Linq;
    - X& v' K' E( ~5 q- z3 S
  4. using System.Net.WebSockets;0 Z- f$ M' @, g; h- q
  5. using System.Text;
    8 a) K+ B% t: ~! p9 {3 O: z& B2 {
  6. using System.Threading;
    9 r2 W4 K7 h  g! a: ^" v$ M
  7. using System.Threading.Tasks;; g5 ?/ `" n/ T0 V; S7 r8 \  o/ o! M
  8. using System.Web;
    0 Y+ V  F- ^, F
  9. using System.Web.WebSockets;* ~& o6 ?+ J  ~2 C

  10. ; n# L) ^, ]# h7 P- F5 V8 |

  11. : H! P/ n7 Y9 [$ z
  12. namespace WebApplicationWebsocketHandler  Z* X8 z  N& `- x+ ]' U
  13. {
    / Y: B% `1 X% X2 Q1 A: H1 d/ ~
  14.     /// <summary>; X! l: A+ D3 U( n
  15.     /// 离线消息
      c& w  b6 ^" ]0 T
  16.     /// </summary>
    : }6 l4 ?- q; o: w' O1 `% R
  17.     public class MessageInfo1 ?8 s: u% c4 `) y  {6 C: g7 [
  18.     {9 X4 I' e, ]8 S# l- [  x) I
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)2 R, L. a, }  E0 b7 o
  20.         {
    * Y* ?8 c9 C( @9 d' ^
  21.             MsgTime = _MsgTime;
    ! W. m. X; @) O+ s
  22.             MsgContent = _MsgContent;
    9 @( F) j7 D; @; v& E: Y
  23.         }
    3 `) x/ d4 I  n6 R' z
  24.         public DateTime MsgTime { get; set; }3 Q- ]& _( P$ p$ r. K# A
  25.         public ArraySegment<byte> MsgContent { get; set; }* ]( g/ q. F* L6 f% W- k
  26.     }
    & k0 [* J1 i8 N' c8 ?2 p
  27. ' n7 S7 U0 I& `/ y* g* W

  28. : z( ^3 o2 c7 X+ P$ y' f  t9 {

  29. ) I5 M! B. d0 h: ^( E

  30.   G2 r, k# J2 i/ K% q; T
  31.     /// <summary>
    , f1 ]9 d. k/ I$ g! m- ~& f
  32.     /// Handler1 的摘要说明& X" i# L' r% n9 c+ f
  33.     /// </summary>6 ^2 {% T9 `7 R+ F
  34.     public class Handler1 : IHttpHandler/ v* W6 x  M4 {4 h: r8 t
  35.     {6 ]5 ~: I# X/ I( W$ k. X8 Z+ x4 T
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池/ [. F# @2 t; h" f
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池3 u9 M# ^. y# I: w; C4 k5 a- a5 f
  38.         public void ProcessRequest(HttpContext context)
    - z0 M2 B# n3 A; T: J- t  Y/ A* a2 l
  39.         {
    5 f/ H, _  Z& }. [
  40.             //context.Response.ContentType = "text/plain";
      r4 ~. o& ~* t5 E- V0 e
  41.             //context.Response.Write("Hello World");$ ?$ k9 ?% q; v, O
  42.             if (context.IsWebSocketRequest)5 n" L2 w2 O  U4 a" T
  43.             {9 T! Z1 s/ a' O) Q
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    ) K: w1 ^, {; s, j) j+ p8 W: i
  45.             } * f8 u# ~( o4 T6 U4 o) S) d
  46.         }
    5 c- U0 a$ v- t  h5 c7 Q! Y- W8 ?
  47. * h( |  q! t' ~2 h( w8 m* ~
  48.         private async Task ProcessChat(AspNetWebSocketContext context)" }; o8 R9 l/ g1 _6 q( o
  49.         {
    - x: e0 o7 J% ]; j+ j2 m) ]/ J
  50.             WebSocket socket = context.WebSocket;/ Z& F: ]" a' D
  51.             string user = context.QueryString["user"].ToString();
    : L5 Y- e  A* [0 Y

  52. . i/ t! b( Y  l7 z
  53.             try
    ' k& U( ]% R8 e1 u% `  [: _+ l4 l2 M
  54.             {/ l% M3 M  z, R, y
  55.                 #region 用户添加连接池* S! }$ n! I( r
  56.                 //第一次open时,添加到连接池中/ f' e. p& ]5 L+ H, K2 a& ^3 W' l
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    * r6 r$ L, j, ~. Z- z- n
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    + A1 |6 g- u3 p4 f
  59.                 else
    ) k3 Z) V+ n; t
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ( r3 U9 x6 \, f1 b3 n6 H5 ~5 M
  61.                         CONNECT_POOL[user] = socket;
    8 A; }1 z! D& S4 l* T8 I* e! L
  62.                 #endregion
    6 S, l: L" R) t& Q- h
  63. 3 Y  n# x* [- J' R  n3 C/ P
  64.                 #region 离线消息处理
    $ `) [- p' _4 Z6 C3 W
  65.                 if (MESSAGE_POOL.ContainsKey(user)), {+ j* p( T  M; [5 c+ Z( [: `
  66.                 {
    5 s  K8 j9 w' W2 F  S" l
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    0 U0 o+ f8 W, s2 R
  68.                     foreach (MessageInfo item in msgs)
    / H7 x8 O3 K  u, z
  69.                     {6 v( W5 F& ]6 i+ q
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);/ e) X" L  t% E/ n, G! S
  71.                     }3 Z  S$ C& _# n; k5 S
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息) ?) _  @/ C; T
  73.                 }
    " ^+ O( S) R7 u
  74.                 #endregion+ T6 r1 f0 b. v0 z6 b' h- ~1 K# ~

  75. - u, r4 S3 D. e6 X, @( K! x* t9 A
  76.                 string descUser = string.Empty;//目的用户
    ( M, F+ R7 w) E
  77.                 while (true)
    ! `0 E: Q9 k9 J$ Y! a+ d0 t( C, I  S
  78.                 {
    # Y7 _( ^7 g1 c/ a3 O' X6 ?
  79.                     if (socket.State == WebSocketState.Open)
    & `$ e; s5 Y0 K1 Q4 |
  80.                     {
    4 b; ]% P" [$ s4 K& x# B- k+ q# P
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);) l1 j; m/ c6 H! Y/ p
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);( [  q1 l. E' a7 Y7 k0 A7 o" `
  83. 5 ^9 R5 B" O; l# ^/ ~* K
  84.                         #region 消息处理(字符截取、消息转发)% g+ f. j3 H9 M( H9 X5 W" B4 U
  85.                         try
      b# [* l, n0 E9 o3 E
  86.                         {- k0 A3 i9 d. i0 I. g6 A2 o, B
  87.                             #region 关闭Socket处理,删除连接池
    6 G# B& Y2 p+ |3 N" h  D3 s
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    + U4 T+ c9 R2 O% S1 E
  89.                             {0 W0 {3 g6 W! p+ ?  C
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
      o5 W/ z: |) U' L9 J, I5 G7 ^" h
  91.                                 break;! n2 o" Q6 U! H- O9 X
  92.                             }
    6 g2 Z& M$ M9 C/ a7 n- o, }. B
  93.                             #endregion
    " x1 t" \% L& |6 L1 q: f1 m
  94. ) H# m5 f; b' v8 W0 T
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息$ ^) g0 i; F; G# S
  96.                             string[] msgList = userMsg.Split('|');
    4 I' v1 w% ?: N/ Y+ L
  97.                             if (msgList.Length == 2)4 a7 m- ]- G$ i* ~, C6 W
  98.                             {
    % b1 k7 V0 M, }4 F9 i+ p
  99.                                 if (msgList[0].Trim().Length > 0)
    * p7 V- R8 x$ A# u
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户5 s" d7 B9 \. a5 h1 {
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    6 H9 X3 x- s. c4 k
  102.                             }
    " o3 L  \  h0 U. u% @! J
  103.                             else5 o/ J5 R. l) H- ^% T5 [! b
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));  t" u7 P0 n3 f# I) n+ B% Y

  105.   V9 b3 P; R' C% j! A; r6 s; q* N
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线6 V# L5 e) M  _! N- c( N' M9 H9 J: S, ~4 t
  107.                             {
    6 I7 e" c( Y7 _$ e, f
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    4 s' L) c' ~5 E' U% {/ }% @* p  h
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)/ M. G. j5 N0 g3 a( `
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);' a" H# [6 i; ?2 O0 L/ j$ S
  111.                             }8 Q$ ?" l9 v" \% Y3 R5 [+ k
  112.                             else
    , @3 R1 G- z2 c& }' v; j, j4 Y
  113.                             {
    5 V: |& [8 f/ ~: [+ V
  114.                                 Task.Run(() =>
    1 _$ u# G! N, l& P6 D1 L
  115.                                 {, a8 C8 T, @- D% K$ N
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中, L3 N. ^6 t0 c, B! k5 |0 x9 o
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    3 Z' ]. B+ C2 w- V+ B
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息, o7 a. m9 M: h6 |/ K
  119.                                 });
    0 D$ X2 G( t! ?0 V1 k( k& d% }
  120.                             }
    0 Z, ~& H6 v2 g3 `" `- n+ d# m9 l
  121.                         }( A' R  N! Q$ ]4 P/ k
  122.                         catch (Exception exs)
    ' r. n1 O9 m3 d. }6 }
  123.                         {
    $ M, |" \- ~1 ?9 N' w% R
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    : V8 r& f2 d* K7 G  R1 b
  125.                         }
    - ?/ F! t0 T# {
  126.                         #endregion8 ~' d, @3 N* s0 s
  127.                     }
    + o: P4 C) Q! n$ _* R3 t- c( t
  128.                     else
    ! D3 P) N- j( n
  129.                     {
    ! u% e" M6 {( {4 c) b
  130.                         break;4 W+ h8 K# b* h$ i9 w1 t
  131.                     }
    1 G! L- j: u. Z/ Z9 @
  132.                 }//while end
    $ c: i7 ~+ w" e% D1 H) A
  133.             }1 S( j# e7 `  `  I
  134.             catch (Exception ex)
    7 @$ F! X0 d- [
  135.             {
    . E# n1 B: h$ [: i2 X
  136.                 //整体异常处理, P; |8 H# H1 K3 E' I) p+ @
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);+ a, {' {4 N8 Z6 r
  138.             }
    : d' i6 ~& O& n4 d5 Y
  139.         }
    8 s# s. @' \* X. T+ ^- E
  140. / u$ P, T; l6 s* N' z1 R! H# j

  141. 3 t4 c1 |, `* h% g
  142.         public bool IsReusable
    4 `* G8 L2 p) _1 R2 ]
  143.         {
    9 Y/ }- Q- W8 S% C  N1 s5 }
  144.             get
    - K+ q% D1 j: l; M
  145.             {, {5 q2 Q2 z" B* n1 `
  146.                 return false;% v1 d" y+ p& ^  N3 w- P* t2 |7 W
  147.             }
    ; Z/ O* v5 `% f- C' O
  148.         }
    " ]0 J' w" e5 d
  149.     }
    ! N9 [- ^: I# ^% q; x, {' \' G; }7 c
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
$ L: u7 l) S" r1 Z6 c  H
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 17:21 , Processed in 0.062581 second(s), 23 queries .

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