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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
( ]% X: h* g8 W5 T+ [- Y
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    . G0 c: {4 V( y' d# x# l3 a
  2. using System.Collections.Generic;
    : t& }# {9 h0 |" z
  3. using System.Linq;
    * @& R9 l0 R7 M2 R' b$ ~$ l; h
  4. using System.Net.WebSockets;+ F. g  ^1 I" b+ T, a! y
  5. using System.Text;7 e" P) ^  c, E. q
  6. using System.Threading;
    1 H6 m& i  }9 l! ]6 o. L
  7. using System.Threading.Tasks;
    " a) A6 M3 K0 Y) k
  8. using System.Web;
    - J- ~- ~3 l4 d9 c6 c- `
  9. using System.Web.WebSockets;2 ^) ]# I8 }% F3 z0 F8 s" p

  10. 7 P+ ~  t# u) U6 t$ U5 c$ E

  11. , {$ i( f% e, r6 z9 s6 U7 A
  12. namespace WebApplicationWebsocketHandler" T" Z5 d1 f7 N- t; }$ M
  13. {
    7 _/ K4 _8 i" G# L
  14.     /// <summary>
    ; p5 p5 s- [% U" c( V7 ?& J
  15.     /// 离线消息9 t9 C+ \1 t9 c% ?3 g% r1 f% E& q
  16.     /// </summary>
    # s- a! o  m3 e6 v7 h
  17.     public class MessageInfo
    5 F# I4 i4 i' h2 R. s
  18.     {% m& {. l2 ~- H9 b. W
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    , p/ @$ L+ {9 P7 g- E
  20.         {
    4 K- @1 ~: t; u
  21.             MsgTime = _MsgTime;. `, ^# A4 W. E$ \
  22.             MsgContent = _MsgContent;/ |2 @$ W2 Z/ m' v  a8 q9 k
  23.         }& g! h/ D3 P' o# ~" Q1 u/ l
  24.         public DateTime MsgTime { get; set; }' x" y# k% F1 b0 V8 D) {. L
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ; H8 a7 i: F4 h. K- i3 B
  26.     }) O+ i: L& U7 A) b

  27. : E8 r. [) z5 Q; E# k$ h( D/ A
  28. ' u2 ?  z% H& D
  29. / C% s# Y; O' V
  30. # X' h4 z% _2 k& l* P  i, I) d/ b  C
  31.     /// <summary>! }% j; P* O+ }- p" @- `9 p: y
  32.     /// Handler1 的摘要说明
    6 _; g& ?' t7 t/ }* l" \# n: _
  33.     /// </summary>" @* r; G3 T. a0 Y
  34.     public class Handler1 : IHttpHandler
    5 ^4 b8 T7 U: e$ P" u8 }
  35.     {0 d9 P! f; S1 y
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池2 S7 D4 ^% }1 z8 O4 W  g( r$ o9 [, G
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    ( V* G: z' @1 Z' t$ [
  38.         public void ProcessRequest(HttpContext context)
    $ e/ t' P+ q1 q0 W
  39.         {; e6 f1 ]( Q8 i! ^# p
  40.             //context.Response.ContentType = "text/plain";
    ; [/ S! V% H2 ?+ E. n4 \% y1 C' s. r
  41.             //context.Response.Write("Hello World");
    . i% I8 [" r- a
  42.             if (context.IsWebSocketRequest)$ l# O. `! T3 h7 S7 m0 I
  43.             {
    . Z0 y( |4 W" x
  44.                 context.AcceptWebSocketRequest(ProcessChat);4 l# ^2 n! D4 c% T' B/ a8 b; X0 N
  45.             }
    ! \( ?3 Y5 I5 |! @  b3 C" h
  46.         }4 C9 k5 X/ b6 p$ [, V" Q
  47. - F& Y# D/ c2 }6 \3 A
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    3 K8 B- e; R* x. s. f
  49.         {
    1 i, o9 [9 W5 d4 G
  50.             WebSocket socket = context.WebSocket;: i" h) W/ _0 |1 v, V
  51.             string user = context.QueryString["user"].ToString();! w# ~: T, L! ~1 d' D) [
  52. 7 y( o5 n/ X: u# R) {% w
  53.             try
    1 h% _( _! d7 n3 a4 h) v
  54.             {4 |7 ?$ p7 E0 P; ~6 O
  55.                 #region 用户添加连接池. [1 ~7 o% L  m2 M! r! N4 E/ K6 k
  56.                 //第一次open时,添加到连接池中& m, \6 C  W+ R2 C% Z8 }
  57.                 if (!CONNECT_POOL.ContainsKey(user))3 ^2 _$ I0 Q& q# O% e8 u
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加8 ?0 a& [0 f; K
  59.                 else
    ) i# L3 P! Q0 Y  A* e& [9 G- \& m
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新1 i9 }) {* O, J+ L) T
  61.                         CONNECT_POOL[user] = socket;( k; u( i% I+ F* F$ q/ y
  62.                 #endregion
    ; V6 D& ^" c( S  g5 Q
  63.   e4 j9 l! q, l) i, B
  64.                 #region 离线消息处理" W  W  I0 L4 S0 [, t7 L1 N
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    9 S! ]6 {4 {  |  ~; k0 k
  66.                 {
      q8 S5 W' T. ^
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ! E/ }- G% b- a) e+ j
  68.                     foreach (MessageInfo item in msgs), K. j9 l, W2 U0 R6 J% e
  69.                     {
    ' @' V- G9 Z: {# b2 R' `6 b' i
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);+ B$ x$ L+ W/ v5 d2 L
  71.                     }
    3 h- H& f; Z3 }
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    : k! o- [$ }; b. _' ~
  73.                 }
    ; h% W8 T# X# l4 V' @4 U$ |
  74.                 #endregion7 l5 W0 D8 Y7 Q2 s$ ^3 a

  75. 7 ^$ H% j$ @* Y4 m
  76.                 string descUser = string.Empty;//目的用户' U  T" U* k5 v2 k; G( g6 o
  77.                 while (true)0 |6 i3 D8 U& f& ]7 R
  78.                 {
    ! y- F& d! f, n: ?. R7 C
  79.                     if (socket.State == WebSocketState.Open)$ w, s7 ]% c8 F5 Y& [3 O' T  m
  80.                     {6 o  P; y) c5 n2 ?
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);6 B# Y, t  s  G/ l. X% N9 d
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    ) A% t, v7 T( O( k/ V* A$ L1 V
  83. 8 ]1 |2 n8 ]* }  }  H
  84.                         #region 消息处理(字符截取、消息转发)
    . l( O* l# z, P, X8 z! o
  85.                         try  [7 F6 \' G2 ^9 \% Z2 |
  86.                         {
      Y1 t2 M  \9 b4 |7 j" m" \& \+ l
  87.                             #region 关闭Socket处理,删除连接池
    6 e' a9 m+ ~* S
  88.                             if (socket.State != WebSocketState.Open)//连接关闭8 k! ?# H, F4 U! G* r* @4 |+ I$ V+ G
  89.                             {2 |+ T9 s4 O/ Q+ Y
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池* X+ m$ I4 T2 r, P' T3 V; O* A- g
  91.                                 break;
    ' N9 O; g# h8 L  W+ f; S, @! ~
  92.                             }
    , k6 T( W3 ~; w8 B
  93.                             #endregion
    5 J' M6 l& v$ }( d  v! Z4 q4 r% n

  94. 0 d3 A4 `/ O9 D
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    5 r' X, x% }  j* z3 h* O9 W
  96.                             string[] msgList = userMsg.Split('|');
      [8 k! y* Y/ u" }5 n3 w1 ?! Y
  97.                             if (msgList.Length == 2)2 f3 L7 f7 s! C4 s
  98.                             {+ ~0 V+ C8 d& [: h1 H
  99.                                 if (msgList[0].Trim().Length > 0)
    ) k9 B7 x* ?) a, \" o
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    8 A; {; L, C' C8 I6 z) O
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    * s" k; Y" d2 r
  102.                             }- j+ ?. N6 F% b, R
  103.                             else
    $ ?6 C# C" M( y& P$ I. v
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ' v, `, A- M, z9 P6 l

  105. 7 ~' t5 [( Z' p+ ^  w4 W" Q+ M
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线, G) A& m# J% m& ~# Q% H! f
  107.                             {
    : l  M" ~" m) F; p, e+ ]
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端( L3 [; z( \2 l
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ( P0 F" K. Y% w* C0 ~1 ^
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);& m* l$ }. T8 l! C+ ^7 D/ i2 Q8 F
  111.                             }- X1 n* _7 O+ b8 s% j5 |: G* i
  112.                             else& ?  ~( P6 Y5 }: c8 d
  113.                             {4 t0 d, O3 T- d& c) R
  114.                                 Task.Run(() =>
    + N" q5 X7 m- |( U
  115.                                 {' _6 `) f( i: D# P; h6 E
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    % u$ Y- k% o- x* Q6 Y1 X0 l
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());% a7 e2 {2 z' c
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    $ a& Z/ a$ k8 }
  119.                                 });
    * \% I* |4 S3 R& |! c: H; a
  120.                             }
    ! d- F8 U6 |$ J. R( c# q
  121.                         }
    - {, q) f6 T8 z
  122.                         catch (Exception exs)+ q) T  _( Y( m- ^- B* `* I6 t
  123.                         {& _' [% i. \: n' w, A) C
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息8 f; ^" B1 K- n6 ~" r8 ?' b
  125.                         }
    # d$ n# u5 p5 u, |
  126.                         #endregion; N4 D5 x0 E% d
  127.                     }
    6 j( f; t- d, i4 g. J
  128.                     else& H4 g9 P, O1 N, d8 y
  129.                     {
    ) |5 f$ A" E: y6 I/ A! s, V
  130.                         break;  x9 o! t8 _. Y; ^+ A* B
  131.                     }+ w+ Y8 P5 e. \" c4 ~
  132.                 }//while end
    1 d+ x3 Q9 d* m4 v: H& G# \
  133.             }  L, h% H3 C2 ?0 E: K  J
  134.             catch (Exception ex)8 j) x# S) w9 \. ^* T! A
  135.             {# g) j2 Y" P" C0 m
  136.                 //整体异常处理
      p. y3 T3 G+ R* @2 K' Z
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    5 _5 j$ ?1 S% y% U$ @: V4 O
  138.             }  {2 o* }  C- E
  139.         }+ G# E& S0 D  ~" ^

  140.   y0 @0 K: y4 a, _
  141. 7 g4 f5 [% R; o
  142.         public bool IsReusable
    ) N/ z  F+ v, x
  143.         {
    ' {& F2 z3 v/ W* B3 d- Q) m( k
  144.             get
    0 T0 }5 _4 g6 t# H
  145.             {1 @, P! ]) T+ \/ W" V, u3 ~
  146.                 return false;
    - o: J& t+ v0 s9 W# X, N
  147.             }' A  K' ~1 R6 n3 d4 d3 ~3 @4 w. q
  148.         }' C9 C8 \# Y2 S1 {
  149.     }
    ; |2 T8 y7 Z, h' e
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
$ X: ~# G9 c* `4 |
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-5 10:34 , Processed in 0.118666 second(s), 22 queries .

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