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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
* m0 _" @6 C" [3 i) m! Z
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;! D, F& F' j* [
  2. using System.Collections.Generic;
    & D  t8 K; }9 s1 S$ m
  3. using System.Linq;
    $ I# b, B/ j. X, ~
  4. using System.Net.WebSockets;6 S- L+ q  p. s% k
  5. using System.Text;
    & U, z. M& b& i5 x
  6. using System.Threading;
    * u9 J% a% b  ~; i0 v9 i' P* \
  7. using System.Threading.Tasks;
    " z. E3 [  L( b9 f  @5 X
  8. using System.Web;4 ]1 H* r6 N8 ^; Y' r6 E* l+ w* A
  9. using System.Web.WebSockets;
    ( q  F  @% g! [3 I" s
  10. 5 a+ F0 d2 \. q$ M9 c( M

  11. $ k# N" f6 L9 X' \
  12. namespace WebApplicationWebsocketHandler
    4 d0 D# _* g$ Y& s9 i
  13. {! \* c" E* }7 q- b6 q/ G
  14.     /// <summary>
      ~% v/ M* }( b/ b5 }8 M6 O: l$ o
  15.     /// 离线消息, @- h) x. ^, t
  16.     /// </summary>
    2 b* R, m3 Z# N) l; @' E! |$ D
  17.     public class MessageInfo) q# {: d2 f1 M* c
  18.     {1 L7 {! o* X+ v4 @9 |! _9 p
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)  l! U: b& i  T& t7 R& f
  20.         {' J  M8 B- O: W, C) {' s2 J
  21.             MsgTime = _MsgTime;# I$ U; s+ N6 p+ b$ y
  22.             MsgContent = _MsgContent;  w- }) L! i" n* h
  23.         }
    0 u+ A- R" c* J0 v8 z5 _5 Q2 v
  24.         public DateTime MsgTime { get; set; }
    ) W* Z) H/ g/ @6 k+ F! _0 [
  25.         public ArraySegment<byte> MsgContent { get; set; }# r# e$ Z9 S8 b+ j
  26.     }
    + b* A! m# v" {# o8 G. R
  27. 6 i6 v, \( q, p5 ?

  28. 5 _! a9 w, B8 U6 G* N: V$ g

  29. ; ^" C: ^0 i, Z8 e
  30. 7 u( V9 A7 F; v
  31.     /// <summary>1 M( |, \/ M- a* d5 c
  32.     /// Handler1 的摘要说明8 Y6 Q& t, ^7 `. P+ r! _
  33.     /// </summary>8 _3 n6 y' o' c$ P& m1 @$ Z! i
  34.     public class Handler1 : IHttpHandler
    8 Y# R* F8 I- |9 [
  35.     {
      [! I% K: `7 h: `0 @1 I/ q3 h9 ~3 A
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    0 q* O1 Q* i4 E5 |2 a9 p" \/ y8 `
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池. R+ b% L: F  ]. Z# m, G, Z7 t
  38.         public void ProcessRequest(HttpContext context)& L1 Z5 ~1 k0 \) R; s* a* z
  39.         {
    : v, N1 A; D. ?( S
  40.             //context.Response.ContentType = "text/plain";! m, Q1 R" [4 W' U) q5 p% |) D
  41.             //context.Response.Write("Hello World");$ ^* q+ C: o, [7 n6 z$ m
  42.             if (context.IsWebSocketRequest)+ Z  k2 k$ q* Q4 F
  43.             {" v: E8 Y# U, L# c8 p
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    . _. g  H; j6 r9 o6 A0 A
  45.             } 3 k; f  y8 ?0 E! X% P- n/ y9 O9 Z
  46.         }
    ( d: i; N" M0 j/ U
  47. . f5 ^* ?+ B9 f+ F- A
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    : j6 k5 x6 Z. z# V8 C
  49.         {( o5 J& U/ A. d* X3 ]
  50.             WebSocket socket = context.WebSocket;
    : q1 P/ O" L6 z, q. ]# H% |. p+ q
  51.             string user = context.QueryString["user"].ToString();1 a. p( t8 v4 l! Q2 F: h  ~8 r

  52. % k" a; i* l7 z2 ^* A6 T9 a
  53.             try
    # P5 ~% s: ]! U; ]0 _) G
  54.             {  Q7 r3 F3 g1 a
  55.                 #region 用户添加连接池- B. g' x' u  v7 c  T
  56.                 //第一次open时,添加到连接池中
    4 @( j/ O, C$ \
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    ( P( e& C4 l6 c7 t4 o: T
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加5 e2 M6 f: s/ R9 g5 D
  59.                 else! U' J- E; g& e+ L" d4 E1 ]
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新  d9 N: e& p; O2 a: E4 u
  61.                         CONNECT_POOL[user] = socket;
    1 y( j: A  e2 n
  62.                 #endregion
    " m2 \1 x) u( ]% a% z0 N7 h1 @: V
  63. + q2 E$ a* n  Z
  64.                 #region 离线消息处理
    2 @+ ^+ Q  p7 k' ?
  65.                 if (MESSAGE_POOL.ContainsKey(user))2 e/ t/ j: b* p! ]" d* P3 k
  66.                 {: l" Q0 I' s3 e! S! e$ K$ H
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];* j# q( ]& U5 _2 I
  68.                     foreach (MessageInfo item in msgs). r' b3 m( j# R4 T) ]4 m5 D
  69.                     {3 p. R6 q8 f3 f+ m2 L5 l
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);. U. ?* W" o' |* ]7 M
  71.                     }
    ) ?' q7 u# i4 k. U/ E
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息/ z8 g9 g4 s$ G+ |
  73.                 }  Y: O5 T& V2 h: p  J3 c
  74.                 #endregion
    - v+ C2 {- P( Z
  75. 8 `/ F3 f  L8 w2 S% O& L6 n, p
  76.                 string descUser = string.Empty;//目的用户# p8 N4 Q8 @" c6 s% a$ F2 ^7 r% [
  77.                 while (true)
    ; R: P) S! o& x6 G8 d
  78.                 {0 u- N* Y, e7 f/ W/ W- }: X! P
  79.                     if (socket.State == WebSocketState.Open)
    * \) x' R* I. y
  80.                     {
    ! ?0 O2 ^' V5 B- q; f, w
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    : x9 ~* h# c4 A
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    * o9 b) s- d( Q1 x* ?

  83. ' \/ [% |: B4 ?  I3 [- r
  84.                         #region 消息处理(字符截取、消息转发); l. f4 T) x- J4 ~6 G; y/ X* a
  85.                         try3 t1 _# P: ~! o4 I4 F$ u
  86.                         {
    " L$ `% l0 d  Y/ Q5 [% K
  87.                             #region 关闭Socket处理,删除连接池7 [# X3 P) O+ b! @1 E
  88.                             if (socket.State != WebSocketState.Open)//连接关闭6 R3 D0 ]' e: u- `) z* {0 m% r
  89.                             {  \- g$ l1 r0 X5 {  R
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    * |! B2 G6 B( y  F/ v' p
  91.                                 break;! w- N6 v  W2 d' X/ u
  92.                             }9 {8 E( o7 f% y& K" T# u  m
  93.                             #endregion6 [9 q# F+ |# ~3 l" H7 [

  94. 8 w7 q/ y& U8 @
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息1 B2 A3 u, T+ `
  96.                             string[] msgList = userMsg.Split('|');
    % d$ c# t( @2 i( N" ~+ L! s  f
  97.                             if (msgList.Length == 2)
    . i! `( t1 {* d/ ^# b3 ~
  98.                             {
    * V9 S! {! n: e) Q1 J
  99.                                 if (msgList[0].Trim().Length > 0)8 v, Q' [* N! K' f% v
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    3 k; h, B( x, s! \2 T  ^; I7 c
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));5 A* H8 c! q# {4 a5 b# _) Q
  102.                             }1 J9 |1 {1 d) s
  103.                             else
    , H) e# m; F0 t1 l( E
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    * V6 E5 x! u5 n4 P  }1 i) U

  105. 2 _0 K4 T5 l; C+ r' C
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线1 v& `. B0 K* N6 D; M
  107.                             {$ @/ w8 a" @+ Y2 u8 B; z
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端0 x5 ^* r+ V) M) ]
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    1 [: _4 z7 w+ F4 F' I
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);0 r: H5 e5 @* z4 {- b/ {
  111.                             }2 I" l' N% y1 [9 j7 E' i- c2 D/ a
  112.                             else' w9 O' [+ j& E
  113.                             {. F9 k& R% }' u& b: x) H. W3 q
  114.                                 Task.Run(() =>$ ]" @  D& J7 D" J( W' X
  115.                                 {$ X3 Z3 `* E2 A0 g, k
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    9 c+ K4 d$ K; n1 O
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());+ h, n8 r- d( S0 ?. H
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    4 Q1 W/ K6 O9 q% Y2 O  k
  119.                                 });8 K7 _: `, l  y7 U1 n3 o# j" a
  120.                             }
    5 E6 m/ T* u& ^! S. k
  121.                         }/ b' [5 e2 |# c# a; s' O
  122.                         catch (Exception exs)
    : E, H) X9 Y' {: x
  123.                         {
    7 f% \% x7 [4 I7 H$ L
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息0 r" Z; W( I# q# e1 y
  125.                         }
    7 f! R+ ^* F, v( X: m' M0 o" ^1 f
  126.                         #endregion
      G& A' o. S$ V! f$ ~
  127.                     }$ u% o$ y: m7 ?/ g9 H
  128.                     else
    5 t0 K* f% @6 T$ k
  129.                     {( S; P" @; X" ]+ H) e" w
  130.                         break;
    1 W& H3 ?2 @; `: w/ N9 \; x
  131.                     }$ ]1 d5 R( y! f; I% `* f3 y
  132.                 }//while end! N* V9 a, {" M9 g
  133.             }
    # H1 _& q; d; b, D* v8 w# ~
  134.             catch (Exception ex)
    . ?, B; k+ V$ Q7 k' ~
  135.             {2 P/ j5 A8 }2 n8 w
  136.                 //整体异常处理
    ( F" D/ i# q$ U
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    * O! h6 Z; T9 Z; t
  138.             }4 z& Z6 I- x2 R; |% G# x# Z) ]
  139.         }; x6 x8 k  Z" Q9 V8 t; t; N
  140.   \# h6 @, ?& r2 m0 d
  141. $ R4 E2 Q# n* N$ K7 a' o3 ?/ t
  142.         public bool IsReusable
    5 s# ~0 x' A# m  T% ~% |
  143.         {( k* S; [% z; p/ m3 \3 [+ T
  144.             get0 C9 L1 _( n2 V( d0 A( H& }* v
  145.             {0 U2 J4 ]5 J3 v6 X. K6 z( [0 A
  146.                 return false;
    6 w6 N: t5 K9 f3 H
  147.             }
    ) n# P" V: c  t8 y& N; C7 x
  148.         }
    # X, a" w' b, m, q& f  U6 G
  149.     }
    ) r. n7 i% B, @* Y
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
+ m5 |/ g$ Z% W4 ]9 R
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 16:45 , Processed in 0.056907 second(s), 23 queries .

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