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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
- b9 e7 A) H4 k9 d& `
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    * i! S+ F7 \/ n: R; l
  2. using System.Collections.Generic;  B1 c! m; ^8 V& [
  3. using System.Linq;
    + s2 j; o3 Z: `' v. a. G4 d
  4. using System.Net.WebSockets;* @. z# \& n- G
  5. using System.Text;
    6 M, t! Z5 N& I
  6. using System.Threading;
    8 k4 U0 h, x3 D7 z/ i$ B# X2 q0 D
  7. using System.Threading.Tasks;
    ; p) ]) \0 S0 {
  8. using System.Web;
    1 u- ~' ]% R+ }: a- x; B
  9. using System.Web.WebSockets;
    6 W; D: G9 _. s" }' x
  10. . O  H8 j8 S% N- o

  11. 9 \1 b5 u! |5 x. M/ c
  12. namespace WebApplicationWebsocketHandler
    1 T* s5 G  N; b; N8 R+ Q& o
  13. {
    , f. A/ m8 D: o1 k2 z( D
  14.     /// <summary>. A0 [: J5 g1 ]1 ?1 _) h
  15.     /// 离线消息2 ^* B5 i* T9 z& O
  16.     /// </summary>: I/ V5 |! z# S6 z! H
  17.     public class MessageInfo
    / X4 t' d6 [- `# c# n0 ]
  18.     {
      Y7 T' J9 E8 \2 F' n4 T
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)/ j4 q- Z/ a5 N& l. g0 P* {: U
  20.         {
    $ k/ ]" y7 t6 E0 N" l. \
  21.             MsgTime = _MsgTime;
    + p4 B. G4 c. C
  22.             MsgContent = _MsgContent;
    ) F& P9 I7 v6 b( R0 ^
  23.         }
    2 l/ n- b- j  T# l  z
  24.         public DateTime MsgTime { get; set; }
    6 x0 H$ ]' n( a' \$ T
  25.         public ArraySegment<byte> MsgContent { get; set; }
    & @. m, D; i# i+ N0 a. B5 w
  26.     }
    3 H2 H$ \/ K: E
  27. 8 T% X% F+ z$ p$ X+ _" a/ O+ N; t; F

  28. . b5 F, G5 z2 l8 h: i/ O; v, i5 R
  29. 8 a1 H: W6 W/ H

  30. 5 d+ B# O+ C  K# {' T, e
  31.     /// <summary>' ?9 O/ d! Y; F( K) T. ^; k
  32.     /// Handler1 的摘要说明& a# C6 z% p3 H
  33.     /// </summary>
    - }1 }7 V' j3 O1 {! u
  34.     public class Handler1 : IHttpHandler" j9 O0 Z6 F& @1 t( g) }& J+ [
  35.     {
    ' r+ Y1 Z# v, D% P) l: e6 _0 r
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    8 J  R. u. @- ?6 I4 e
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池2 W9 y! [8 ]( ]2 c# n) N
  38.         public void ProcessRequest(HttpContext context)
    ( v, E+ w: Y9 t7 G6 ?1 ?3 B
  39.         {" Q% `" I6 o& S5 b
  40.             //context.Response.ContentType = "text/plain";: g" a8 S! I  z7 |% I
  41.             //context.Response.Write("Hello World");9 i4 O4 ]3 s4 o' b
  42.             if (context.IsWebSocketRequest)4 j& e+ y' h1 @3 l; {/ {+ @! R5 R  J
  43.             {- f9 G8 M% s* P+ G
  44.                 context.AcceptWebSocketRequest(ProcessChat);/ u- E8 j2 U; P! O4 \9 ?( Q
  45.             } " \! T2 m1 ?$ z
  46.         }
    / S7 k" e. ^2 l" C0 X( `
  47. 1 \" N  ~4 g2 \0 J" I. X
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    0 U) ~: Y  ~  ?) f5 @
  49.         {: E8 F' P/ }3 P) v; `, Z7 N
  50.             WebSocket socket = context.WebSocket;. O" e$ Z1 Z/ K( {* p
  51.             string user = context.QueryString["user"].ToString();
    0 T- [) ]9 I3 h
  52. , w, ~' y4 u" y' F& g: F
  53.             try) [4 O- A0 V3 B7 Z) b/ |* x. d* }
  54.             {8 F  T' S( Z5 N7 u8 S! {1 Q
  55.                 #region 用户添加连接池
    / G8 }$ m9 I+ z) G+ U- R
  56.                 //第一次open时,添加到连接池中4 J; h$ u' U$ u+ W7 F  P
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    ! [" F/ U  ^' Z% E: [
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加" s  U$ Q& B& |+ {& V" q2 S3 {
  59.                 else
    # A; ?& Q( W! [7 k
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新+ F: s8 R8 c" \
  61.                         CONNECT_POOL[user] = socket;
    4 Q2 X. L! ?9 w- z- g8 P
  62.                 #endregion
    2 x# o1 R( B, D) x
  63. 9 {4 q" D  V0 E+ N  J( s
  64.                 #region 离线消息处理# r1 D' o  |, W! _& j
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    2 a4 p2 [/ {3 x4 Y4 b9 e: k" h
  66.                 {9 b3 a& Y% Z/ C
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    . W- f1 o0 d; S$ U! O% ?
  68.                     foreach (MessageInfo item in msgs)1 K) N1 @' b1 }" q
  69.                     {
    + i7 z6 L1 V9 n+ c& M9 o5 I/ [7 x( ?
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    0 @1 E2 _* Z0 ^0 B+ q: D. C9 s
  71.                     }" o/ I$ l+ L, ^
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息0 t1 m# e- U! a' w$ \5 J
  73.                 }
    8 `1 |4 S1 P" L# n& H8 w6 Q5 T
  74.                 #endregion% v' X: v% o( d# Y0 p7 w

  75. , }. Y" m: L, @* i) A1 ?/ a
  76.                 string descUser = string.Empty;//目的用户
    - P: t6 k. ?) o" Z) E8 k5 E
  77.                 while (true)
    5 o1 C7 `" h- V" |5 d
  78.                 {& `5 W; s3 h& S
  79.                     if (socket.State == WebSocketState.Open)1 M7 S! U: D' U2 a/ D; V" D
  80.                     {
    1 t, a1 @6 g. d+ p
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    3 O* {1 O' Q* T7 i
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);6 r" X/ a( e' E5 E# _5 T; G0 S

  83. 5 e* k- R6 r1 r4 u; V1 J3 T7 P
  84.                         #region 消息处理(字符截取、消息转发)! k8 Q; h! f& \: Z
  85.                         try8 A5 P3 I% X# ?/ x
  86.                         {: e2 ?1 W% S( p0 T0 i' `# w1 H& @0 s
  87.                             #region 关闭Socket处理,删除连接池
    0 N9 V! |1 S, \$ R; _/ ]  Q
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    & {# F; b! v3 P
  89.                             {; k: f1 u- b5 a$ h$ V* W- E7 ]* a
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    3 z  _) r8 p0 T; V
  91.                                 break;; z; F) p, m$ w. X: H# i0 r5 A
  92.                             }
      w' Z& w9 f+ M- v* V: S
  93.                             #endregion
    + {% F; U# {- ]: @; N3 X, I& l
  94. . k/ f6 Y) F1 ]) f
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    4 d! M" C9 A7 Y9 E
  96.                             string[] msgList = userMsg.Split('|');
    7 G- O: y4 Y( p# A4 ?/ Z7 [& M9 K
  97.                             if (msgList.Length == 2)4 O' s% x; k$ |6 ^
  98.                             {
      w! u! L& r! C1 T/ x. `" }
  99.                                 if (msgList[0].Trim().Length > 0)
    % ~" @5 t* q  b- M% s, w. t
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
      X! d& Y" W% w7 X4 V8 g
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    $ C6 P6 N9 W! v6 A+ z- i, n  C
  102.                             }
    5 G# b7 `6 Q( z- i! n9 Y' b" a
  103.                             else
    ! i; [- K6 k( q6 Z
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ; m& C- G( G5 z8 i* ~( O! v! {
  105. # x, x, W3 M. Q) U- S, @, Y
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    4 y, Y( w- V: }; \2 t: P% _
  107.                             {8 t4 Z( H, I5 _* z  ^! S; T
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    - j- z; y; Y% h" Z: K/ o
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ' w( N2 _' w% }, d; k) w
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
      ~9 I' S+ B, d& [
  111.                             }8 s& k1 u8 h1 v- O; ]9 h
  112.                             else  ^( k2 @& I5 ^! v
  113.                             {' e* R( z3 O8 f7 m
  114.                                 Task.Run(() =>
    & p0 q6 m2 M4 E/ J* B6 D. V
  115.                                 {& c, N  L  P& M
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    / l+ J5 w6 O  q; z5 Y  x# S
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    5 l/ A+ j% h  p6 j4 w) V5 ]
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ) ?4 u  u5 z8 E4 P
  119.                                 });: |# [1 `( K3 K- e/ M: S8 a4 N$ C1 H* h
  120.                             }
    4 Q8 [  r& C9 o/ @1 Y
  121.                         }! l9 @+ s0 C0 t2 U- f
  122.                         catch (Exception exs)% v4 c8 f& W8 m* c
  123.                         {
    ! Q9 g' y5 E6 q7 X) v6 z
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息5 `0 d7 v! w" h
  125.                         }
    $ w. }& p$ N' H' i) U1 f
  126.                         #endregion
    * }6 U8 P0 M: V. I" R' R
  127.                     }# m  E  ~2 b5 Y
  128.                     else' p, Z% y) ^# E' \. I- x5 A8 @
  129.                     {
    2 T+ H4 \, R( R
  130.                         break;
    2 Y5 U9 d& Q" O  `2 M$ v. k+ i
  131.                     }
    1 J3 B( V9 |( K" k4 o6 C
  132.                 }//while end
    * Z) y+ V3 X* Y8 j- G. m+ |
  133.             }' v7 y  A: V* C
  134.             catch (Exception ex)" H- m. R) p' O, Q. Y
  135.             {
    . T5 H7 v! u( n4 B& j: \
  136.                 //整体异常处理) v) r9 a" j9 D! p9 p- P: Q
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);! _5 d4 _) n. B7 Z
  138.             }
    ; e9 K- }- @9 z2 \) x9 s- X
  139.         }( g! V2 b, M* t% T: e# Z& |0 z+ l4 m
  140. 3 n- D. }, c% `) m
  141. : ~2 a4 b! _  c3 B) H
  142.         public bool IsReusable6 P7 }1 `# D2 E4 q
  143.         {; |8 @% {# s# M
  144.             get
    $ T1 v# d  z$ P7 U
  145.             {6 p  A; {4 J' H
  146.                 return false;
    % t, d! I% c7 J# f+ q
  147.             }) @3 ~8 h& f- @' W8 S2 g3 T
  148.         }
    2 `' a/ S5 b% t
  149.     }. R) v  u! ^8 ?4 @
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

/ h8 \' J! s0 k, X8 }- L) I
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-5-2 16:40 , Processed in 0.059068 second(s), 24 queries .

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