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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

8 z( F9 J6 V& O3 O+ ?* \" a/ m7 g) y& ?
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    4 e# w- _5 H. s% B' a3 v
  2. using System.Collections.Generic;  }& l/ S& z* k1 }# l5 _+ D9 g
  3. using System.Linq;
    + [3 G7 n# u( X$ _
  4. using System.Net.WebSockets;
    + V  C; ~( l3 Z; J9 j5 [
  5. using System.Text;
    / u, }0 G$ z0 U( @* ]
  6. using System.Threading;9 @# T) w* v' H4 j' X7 D( G; {- z$ `1 Z
  7. using System.Threading.Tasks;
    4 S  X3 Y( o5 V- i3 G5 M/ g
  8. using System.Web;7 a- R1 Q3 Y( s+ c+ O
  9. using System.Web.WebSockets;% Y0 a1 ^2 e* S! \

  10. & E2 i+ o8 @. T# c- B

  11. 1 Z, W4 x$ x  J
  12. namespace WebApplicationWebsocketHandler: ~$ [3 G2 A3 e& A' Y# p
  13. {
    0 Q* O) M3 L# J& i6 l. C
  14.     /// <summary>/ X# j) m8 ?/ V4 B1 O7 j" E2 n/ O
  15.     /// 离线消息6 q1 z- \/ m8 H& U2 k
  16.     /// </summary>& A, D0 L& E* l. K; |9 _
  17.     public class MessageInfo
    ) K2 `8 _% V. u3 j$ y/ \
  18.     {$ q1 x, x0 x" P; b) o3 e1 R" C, e3 T
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    : G2 h3 l; F3 `0 K2 J8 F; t
  20.         {
    # l  V3 z* m* b7 g) p4 G5 t
  21.             MsgTime = _MsgTime;5 t* `, m1 l2 [( z& u+ c: L: A: ]$ g
  22.             MsgContent = _MsgContent;1 w9 ^8 e3 w: s7 z! `- N# ^$ r
  23.         }
    ( F  L5 m- T% k- w/ ]
  24.         public DateTime MsgTime { get; set; }' c# z4 n8 P! C9 b& X7 f5 `8 i8 h
  25.         public ArraySegment<byte> MsgContent { get; set; }
    / j0 I& R; U* F) c
  26.     }' d4 i* c$ t; V$ w3 ?3 [! P
  27. / f* x5 f$ E4 _; |6 Z2 Z
  28. ; B+ K4 I) M) \8 A! s
  29. - f, L7 A$ E0 Y6 u7 [5 x
  30. ( Q( _& l8 \  Q9 b* }. V+ X
  31.     /// <summary>
    + N* A5 }7 X, _
  32.     /// Handler1 的摘要说明
    7 i4 w& s  `2 Y* g7 N
  33.     /// </summary>
    & f* ?0 A0 Y: h3 G% e. Y
  34.     public class Handler1 : IHttpHandler
    ' T$ k: l& n" K# `6 v% U6 G0 U
  35.     {
    4 Y3 C. a; [  A- _6 z0 x
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池; @7 u  Q0 Y7 [$ I# M
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ; q5 G  S1 B  @! N. D, s: s
  38.         public void ProcessRequest(HttpContext context)
    2 D& Y: m' V. i- `: S" v, d" {% c
  39.         {
    ( s, j/ j% z- _
  40.             //context.Response.ContentType = "text/plain";2 {1 a. }* K6 P  w3 N
  41.             //context.Response.Write("Hello World");
    ! y/ |# j' ]8 N- o6 `
  42.             if (context.IsWebSocketRequest)' G8 F; m. k: t- o  i4 f5 X& T0 V9 A
  43.             {) @5 B( }! q! a6 N4 p! K
  44.                 context.AcceptWebSocketRequest(ProcessChat);4 X9 e8 q  [5 l( v1 B- y, A
  45.             } ( N4 x" [6 ^- D+ j
  46.         }
    . S& _7 p! y# |- l2 D! f2 `

  47. 8 q4 s+ B# [' n9 V6 k) E
  48.         private async Task ProcessChat(AspNetWebSocketContext context)$ h$ ^1 p+ H: ~/ ]; Z8 {  F
  49.         {$ Q+ A+ j9 a# j( w2 f
  50.             WebSocket socket = context.WebSocket;
    3 b# R! t, o5 j- ^& \9 z! {7 V5 s
  51.             string user = context.QueryString["user"].ToString();3 m7 L) [3 K/ I! C# s2 _- F% l

  52. ' N4 P% ]; H' z0 U7 Q
  53.             try' D9 o+ ~( N7 k# b
  54.             {
      R2 k! I+ ^* d% ]/ s# Y$ _
  55.                 #region 用户添加连接池8 C% a# i1 k2 J$ R) g
  56.                 //第一次open时,添加到连接池中' T1 o( ?1 U: Y" H4 u/ g& {5 v
  57.                 if (!CONNECT_POOL.ContainsKey(user))3 k! z% M: G2 v$ D5 j
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ! P8 o4 T2 {# t1 W0 l7 l  ]' T
  59.                 else6 i2 M7 r) \, W, U
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ' i. E. F' P: L& l9 s
  61.                         CONNECT_POOL[user] = socket;
    , j3 |; ?7 a2 U
  62.                 #endregion0 I) S- d8 I- k9 W; ?
  63. ! Y) B. L& z: }4 z4 D
  64.                 #region 离线消息处理7 D6 \0 W% e: q% G5 w: t/ t
  65.                 if (MESSAGE_POOL.ContainsKey(user))2 \. {! `7 v: I7 ^- K' w
  66.                 {
    3 }2 ]" q2 T& |- k/ x7 ?
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    5 g. d+ A. _2 K  q
  68.                     foreach (MessageInfo item in msgs)
    ( {! W% Y5 X) @5 `* y: R' }
  69.                     {' J; w" B) T& m! T4 ^
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);" {/ J2 ~$ }( b6 W
  71.                     }, H9 F9 m* J3 c! D+ Z3 G% j6 y
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ) |& k; P8 W0 ~
  73.                 }
    , ?2 c7 m" ]* k3 m7 k' S
  74.                 #endregion+ x- {7 d8 ^0 H2 T) F0 p+ a
  75. 8 Z1 f7 @& x( k) W3 H, I% b8 v
  76.                 string descUser = string.Empty;//目的用户
    & s" @6 M, m0 B2 f# H/ t, _4 I
  77.                 while (true)' s  X; a' r0 V: |/ y
  78.                 {* ^5 S( R! t! U; x; D4 B
  79.                     if (socket.State == WebSocketState.Open)
    0 H; F: j6 q* ~) f7 I6 u
  80.                     {, N" g6 z3 z, t2 {. H
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    9 y: u+ Q7 W8 u% _
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    6 y3 U; C, `+ ~8 l: R

  83. ( T1 S2 K3 Y4 a
  84.                         #region 消息处理(字符截取、消息转发)1 y* O/ g$ {9 T9 b/ V) ^6 o
  85.                         try
    ! L. o! ?3 `6 O8 `' S; M+ G
  86.                         {  A1 H& @( @( l8 C
  87.                             #region 关闭Socket处理,删除连接池7 h" S' C! [- [8 {( D4 {
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    * @3 L7 D5 B  q( n) |
  89.                             {( H2 Q" R* s0 W- z" c
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池1 f! g& v2 X& b' \, \3 W; f
  91.                                 break;4 W7 a- Y0 G& c: q9 s2 N
  92.                             }. l; p7 |/ d0 ]: O
  93.                             #endregion
    - K6 @1 Y1 s8 I  K& P- D& L

  94. 3 g& I; _, j  ?( T- v. x
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    # \. e" F: h: y& O  W4 h
  96.                             string[] msgList = userMsg.Split('|');; k4 E! y* h( H- a2 f
  97.                             if (msgList.Length == 2)0 p  V  w2 X8 `/ j9 e: ]! i+ V
  98.                             {
    1 }: M; r, [- y# q9 o
  99.                                 if (msgList[0].Trim().Length > 0)
    4 n) ?3 Y/ n: [' m, P
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户5 V7 u6 I7 r- Y8 Y1 L; r
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));1 E, S: G" [& H" o
  102.                             }
    - [2 ]( T' v6 f& v
  103.                             else, A* E6 ]7 K5 l" u
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    $ v" }( R, ?7 w" w6 \

  105. % L& \: Y& E3 {0 t" L
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线$ n3 B1 ]0 V! k+ S
  107.                             {& y7 G- s* \0 O
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    " |/ U9 P' Y" z' c5 L; G4 H( U
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open); k  W* L$ H9 B) v% R- J( T' n& T
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);$ A" c$ K$ V, Z9 `: @3 f
  111.                             }
    3 [+ m0 {5 e5 s2 R
  112.                             else/ V8 Z. c- w% [+ R/ r6 F- Z; N
  113.                             {
    5 U- F- G. ?7 v& A, R" V$ t1 v
  114.                                 Task.Run(() =>
    + e' T; C5 Y8 L
  115.                                 {1 |3 H1 Q/ T: O. ?( S
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    7 b7 p( Q0 q. u& _7 H5 W
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());6 V( I! g! U, ]) ^, R& Y1 \1 @
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ( o- t5 |7 R  |, G: |! v9 l' _
  119.                                 });
    % O# n8 c7 Z9 a: G% m& j0 Z% m' e
  120.                             }
    $ e5 d0 d  B$ o8 P; j
  121.                         }
    6 {1 [: ]1 l4 Z: q  M5 x+ L+ _
  122.                         catch (Exception exs)0 F7 p' |2 @/ f! @5 w- s
  123.                         {
    # x; W' G6 u3 G
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息" R4 C2 M) v4 s( D
  125.                         }; U( L) H* e6 q* J" q0 }
  126.                         #endregion
    4 Y) `" n1 m$ }# \$ }
  127.                     }( g7 R: a( `. T: z+ a# a7 z
  128.                     else- G$ y6 R! Q2 v- P7 r9 V2 a" G
  129.                     {- b( [: X8 m) h/ W/ r
  130.                         break;
    & k- c2 m: v* L( B
  131.                     }9 U( o1 b0 |% f# E) w, R9 m* y
  132.                 }//while end/ O2 C% D; U  S0 L( f
  133.             }
    0 Q6 t9 R7 a, \
  134.             catch (Exception ex)! N3 q$ W! g6 d4 j' G3 M3 ]+ c
  135.             {) \5 a& j5 H+ q# G. V$ j4 z4 A, \; [
  136.                 //整体异常处理
    6 d! I+ Q; |6 A  u/ ~5 g9 F2 i5 d+ r
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    - X. R9 T2 G- V# ^" O. ]9 V/ ]
  138.             }
    - f% [. H5 j7 J7 |! V/ `
  139.         }
    3 Q# X5 E5 h8 q
  140. $ U* V4 \* {3 |$ e2 S

  141. ) T/ y' Y- t) L3 f* y& j
  142.         public bool IsReusable( |; z% K& u( ~8 ^: G" l8 F
  143.         {
    ) \% ]; m7 G3 N8 S+ m( i% @
  144.             get
    0 d/ m: A: H: o  J) l/ L1 v* ]8 E- V
  145.             {
    3 L" o' i9 i* h/ M0 b
  146.                 return false;, O. G2 d* Z0 K/ C
  147.             }& h9 l( P0 k5 Z/ z  x
  148.         }
    ; R# v1 i; Q3 I
  149.     }1 }0 T+ j0 b! K& r
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
/ @/ b: Z  L$ K/ l6 s% q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-9-22 04:11 , Processed in 0.060315 second(s), 22 queries .

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