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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
% m$ N1 ?' q, s
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;5 I  h4 B, H  @6 `+ F- E
  2. using System.Collections.Generic;
    : C( i1 n4 E: Z  g8 L3 y
  3. using System.Linq;/ l! U+ m/ G0 ]
  4. using System.Net.WebSockets;/ U3 r9 Q. Y( g8 C1 Z# n) X
  5. using System.Text;0 H) m% ^! E% i# D; v- m
  6. using System.Threading;7 l8 \& P+ a1 T
  7. using System.Threading.Tasks;
    8 e+ n. L6 d& F6 _% M0 o/ W
  8. using System.Web;
    ( [) |) ?) L1 k, X8 N! C/ C. j
  9. using System.Web.WebSockets;# {. M0 J& }% A% ?# E* d+ x

  10.   ]  v5 g; }5 ^# Z
  11. 6 J/ W/ J( {8 @* u9 [/ m$ A
  12. namespace WebApplicationWebsocketHandler4 a" y& a+ `& v: v4 c( `$ p& O. _
  13. {7 [$ Q0 X+ x% |+ u
  14.     /// <summary>" h) |  f: O1 H/ V: [  F
  15.     /// 离线消息( e5 A/ @  t9 [! [' K3 N
  16.     /// </summary>" k2 q% A9 f7 \5 R* ^. m
  17.     public class MessageInfo. Z4 s. O3 V5 s, B) v" `4 P+ m" |' |
  18.     {
    & O2 c6 N# C6 o  q8 ~
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)2 r+ ^2 K+ T: b( W8 U1 c
  20.         {- g3 y; s) J0 i  R! {8 i2 l( k0 F
  21.             MsgTime = _MsgTime;
      H9 }3 j( x1 G( o% K; A! Y/ P0 O: E
  22.             MsgContent = _MsgContent;% _  i5 s' L! b: E  x9 c8 ~
  23.         }
    $ ]9 N' N9 V- o: H; l( p
  24.         public DateTime MsgTime { get; set; }, |3 t; c6 c3 u; L
  25.         public ArraySegment<byte> MsgContent { get; set; }
    4 u. P% d9 b' ^8 W& S$ T. \, n& g
  26.     }! W7 g) ]1 w  X1 d* b4 x( x
  27. 6 m2 S$ u. R7 q/ H; Z% {& f1 E% \
  28. $ |. V2 t+ ?6 `" m8 V5 e4 ~3 h# W! H' a

  29. : w7 B& q) m) R

  30. - q% m5 s0 W' s( J& M1 i8 z
  31.     /// <summary>
    , Q0 E$ [, m- o* R6 n) N' J
  32.     /// Handler1 的摘要说明( }9 }' k4 j+ e% ?7 f
  33.     /// </summary>  h4 R2 J9 y9 }# D0 g6 ^
  34.     public class Handler1 : IHttpHandler- W; j- k. t1 R0 q6 R
  35.     {9 ~1 J  Y4 I( _0 I& Z. S. S( t
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池2 _$ F  Y1 u' y: P3 Q+ t$ ]3 o
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池+ B, Y; @, z6 c/ F9 _' w
  38.         public void ProcessRequest(HttpContext context)3 u* _) m7 q/ S3 q7 r1 n; r
  39.         {
    8 D4 }) A) l  U) s0 i/ j  @" Z6 b
  40.             //context.Response.ContentType = "text/plain";  n" Z- R6 e# p1 G+ ^/ u1 x
  41.             //context.Response.Write("Hello World");  b. j; \( y) n: h7 l
  42.             if (context.IsWebSocketRequest)
    ! \7 ?3 y* I9 I  O) O
  43.             {
    / E/ |( k$ L( H; M" s0 P" W
  44.                 context.AcceptWebSocketRequest(ProcessChat);6 a& u3 ^8 k, f4 b  k
  45.             }
    8 f# a$ L( K- @" a' r7 L, `
  46.         }
    $ M& \* K2 k6 N& P
  47. 5 F) K, D3 P" l4 d; a8 g# I, \% B+ `
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    ' G& |( H) n2 {9 r% y, z
  49.         {/ n* a2 }: y6 _& m' [0 }$ I
  50.             WebSocket socket = context.WebSocket;
    - R) f* z' z9 c2 y- V" u" r
  51.             string user = context.QueryString["user"].ToString();- x1 K' k' [) w5 |  s4 @

  52. ! J; f' s2 q6 X# F3 A0 Q) }
  53.             try( P5 m2 C4 V& q! C8 {0 O9 H
  54.             {8 i# b1 y) G# R
  55.                 #region 用户添加连接池% c6 R  l. L7 R. f1 W5 l6 ^
  56.                 //第一次open时,添加到连接池中
    7 l& e9 I4 h& \- g9 W- q
  57.                 if (!CONNECT_POOL.ContainsKey(user))( k% l' G& }: R
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加  k* f# J, {3 @4 v: p8 }$ F1 K
  59.                 else; Q4 W- |) r6 b2 h$ o; B
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新8 S5 n0 R# J) I) I( G
  61.                         CONNECT_POOL[user] = socket;3 @1 G( J6 o% H
  62.                 #endregion
    9 K3 a+ _0 z9 u+ S6 O: K' t
  63. ) F& c3 y  O) v
  64.                 #region 离线消息处理
    ' t% x, o- ?2 ?- L! Y
  65.                 if (MESSAGE_POOL.ContainsKey(user))2 A7 y* Y5 E9 |+ I
  66.                 {
    1 F, o4 z( N( H& c: W
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    . l3 c  Q, {- D7 [5 t
  68.                     foreach (MessageInfo item in msgs)
    4 @8 b. a4 C0 Q5 t5 v0 ~! }
  69.                     {# G* ?2 I4 I/ o
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);! }0 c% r) d2 D/ ^% e
  71.                     }6 l0 n1 q: _: }  U
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    0 o' O7 h6 c6 t& A1 J: h. L: T
  73.                 }+ |4 J' R1 b4 a: X! T& N
  74.                 #endregion
    8 v, j; k$ T7 |0 H. g

  75. : G$ p7 B/ T% i' R! G0 W( X
  76.                 string descUser = string.Empty;//目的用户
    + E, K, M( F7 F9 i0 y- [$ _
  77.                 while (true)5 Z( i4 F% P( r* Y% F7 v+ ?
  78.                 {7 [0 @' Y0 H/ g
  79.                     if (socket.State == WebSocketState.Open)
    ( D# M8 F( M2 Q8 p
  80.                     {  g( C! ]2 f5 Q# v6 ~$ y
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);* r( @5 a, V7 @
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    " `) ]% F/ V& u% G. p7 l1 k
  83. ; D6 p' M, }: r6 ~1 H+ e
  84.                         #region 消息处理(字符截取、消息转发)
    3 V1 ?- c8 X1 r3 \
  85.                         try
    1 e" l! T# B# ?) s7 R/ ]
  86.                         {
    - x! c4 P- o) m4 U$ r
  87.                             #region 关闭Socket处理,删除连接池
    6 e) a4 o, \# j
  88.                             if (socket.State != WebSocketState.Open)//连接关闭" {  J. a$ @) }8 c
  89.                             {
    . `5 q( \' p' l" l/ x$ h/ j
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池0 E, Z( S2 @( G5 K
  91.                                 break;
    - C( @) B% [5 h2 {6 |- h6 e
  92.                             }9 q- M7 p  z( N3 U# g( b2 H/ d% {
  93.                             #endregion
    : e: L3 g% T' |  n# w/ g5 H
  94. 5 Z; E. @$ k2 V6 H; U% g/ x
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息% ?& k, p: Q% H  G7 u
  96.                             string[] msgList = userMsg.Split('|');
    ; c; |0 K2 f# Y; f- y
  97.                             if (msgList.Length == 2)
    9 }/ i; _2 D0 u, M
  98.                             {9 ]1 s4 S8 f! l9 p1 M1 v
  99.                                 if (msgList[0].Trim().Length > 0)/ Y8 o3 \6 V$ ?
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    , `; U0 L1 D' j1 U
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    8 w" j/ ^+ y9 P/ i1 B( l
  102.                             }: U5 X! D5 k1 f' C! S7 L
  103.                             else% A' B6 r; A. X+ q
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));5 m; n4 P; j4 m. [

  105. # w  Z0 u% y/ B+ ?2 x; S2 s
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线! ]. n/ ]1 w& G! Q
  107.                             {. v2 A6 [/ P. B. W
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    3 {4 f# j% E0 ~: v# y0 L) a7 b
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)* n& c! v; E& g$ C
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);' P2 A/ i, R' @( O
  111.                             }
    ' u4 d" L; m, A0 l6 ~! M
  112.                             else4 {# h5 W4 x$ }$ x) J" v
  113.                             {
    / ]$ v% Z( {8 ], ^7 t
  114.                                 Task.Run(() =>& H; m0 @& H6 U
  115.                                 {) m5 c* n9 o& w: Z! q7 H
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中- i- x5 V) w  x$ x; a( @# |& y
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());8 V. A/ a# M% S4 ^# m
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    ! t9 O- i* {* j% m& ?% B7 p8 C
  119.                                 });+ i% ?& f1 `4 `
  120.                             }
    3 k* {4 `: f9 I. L' w3 k+ h
  121.                         }
    & i# U' X9 L8 n- E* ?% S5 ^
  122.                         catch (Exception exs)
    ( U* k3 h( n. s
  123.                         {& E# l7 V6 c. J% y+ }" E
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    6 @8 c' q* Z; P" H9 p0 j. b
  125.                         }/ [% y: i% R; a% Y: G( L- L1 O# h
  126.                         #endregion
    8 _" B" L' `! g3 h9 G0 {
  127.                     }
    / }# B- B# o4 F- W( |! c
  128.                     else
    1 U. o$ Q! H: j5 J  k- T, m
  129.                     {' O% K3 T! x* o8 q" X0 m/ s: Y) R
  130.                         break;
    / l0 p* E  T2 `- o: l# y" `+ E& }
  131.                     }/ w$ O$ r3 h# \6 D. s+ L
  132.                 }//while end. ^  s& V- P; _8 @
  133.             }2 Z1 D2 W3 R# _/ M# ]; ^; ?5 p. D0 A, S
  134.             catch (Exception ex)
    2 ~- |/ A7 x! \# f5 R  Y# B
  135.             {
    , w/ a- n; g$ f
  136.                 //整体异常处理
    / a' X. b- i5 g6 I1 K& E$ u
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);1 d  f" C7 s; s, _2 ^- I: b& w) y' i
  138.             }
    & i: ]% k) J: r
  139.         }
    4 ?% e4 F2 a" K
  140. ) O+ w5 H: T, `& E/ `
  141. . T7 A1 D( T( W0 _8 f
  142.         public bool IsReusable
    # {9 f, M1 X9 K7 a6 u( K9 T
  143.         {
    % N7 t- `/ N5 A: X* t9 `/ N* |7 {, Y
  144.             get
    & \1 K. m3 T- \6 i1 Q9 |, ~
  145.             {
    + p6 C; l7 s6 k. [  J$ N) q
  146.                 return false;$ F' p1 R/ S& ?$ }, U2 h* ~
  147.             }
    3 Z0 h  n3 f2 ^
  148.         }
    3 t* y6 ~3 d% K% [
  149.     }  l2 O1 C- g) V* C
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

  S: ?# K  x; u8 F% ]9 n
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 11:39 , Processed in 0.060226 second(s), 23 queries .

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