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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
$ c2 ~" j# d, s- `
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;. W5 \+ X, s4 t* y0 {* K; o& {
  2. using System.Collections.Generic;
    & F1 K3 ?2 }) `: _) x
  3. using System.Linq;
    % _7 p' v9 a; l" E! y% }0 E0 g
  4. using System.Net.WebSockets;  c; H) A2 G4 S( S  e1 J& i1 s: e
  5. using System.Text;7 k' N0 A4 D. r9 u% ^8 S1 ^) a
  6. using System.Threading;
    * A# F* d; [9 M( ^+ ~1 V- x+ G
  7. using System.Threading.Tasks;
    9 ]( X4 V. ?8 i3 M& M
  8. using System.Web;
    # w  p! Z. V' ]& o8 w8 ]: Q
  9. using System.Web.WebSockets;9 n( U* R+ c: y$ |/ b6 w

  10. + A! p) X8 V0 J8 b7 D4 T* `

  11. 5 r: S3 {4 h4 y4 v
  12. namespace WebApplicationWebsocketHandler' ?2 n$ v0 F; S0 j# V6 W
  13. {
    , ~/ {; m7 e6 C$ m  F
  14.     /// <summary>/ T, h( c7 d& e; @4 [1 _
  15.     /// 离线消息
    2 g% ~# R3 W* \% u& `% r
  16.     /// </summary>
    / f6 z8 ]# M" ^
  17.     public class MessageInfo
    ; k$ {6 h0 b6 g8 J
  18.     {" y1 z+ ~, P* p
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    9 l8 h( m5 t' s$ @
  20.         {( M4 X  Z. N. ^3 g
  21.             MsgTime = _MsgTime;
    2 g8 m8 M; O; B: E3 x3 s
  22.             MsgContent = _MsgContent;
    3 L! k3 U. F2 u& ]/ g" p1 D8 s& `
  23.         }
    8 C; }: u4 Y/ Z' I" x
  24.         public DateTime MsgTime { get; set; }
    3 h1 t- k. Q9 Z& ~9 O" Q
  25.         public ArraySegment<byte> MsgContent { get; set; }
    : Z1 y9 y. Y- C' T
  26.     }
    2 b' O% E3 Z7 C/ P4 q( J. o

  27. . w% W5 w" f! b6 G0 Q/ x' [

  28. 6 ]& \) R- k  q
  29. 8 q% L/ g; R. @8 N, p

  30. 2 b: z8 j4 Q* i2 ]3 N. d
  31.     /// <summary>
    5 v7 |0 r+ |2 t# a9 l. C5 X  g
  32.     /// Handler1 的摘要说明
    ' ]/ u* W; S' \: i) h  @
  33.     /// </summary>' j/ u, l( l& H. H6 j3 v. E
  34.     public class Handler1 : IHttpHandler' p, R7 Y2 k2 _1 T8 u% J' d$ n
  35.     {( g/ t" ?' a6 j4 ]9 _
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池4 x4 k5 e! x, u( t
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    $ m+ {( V' R" |; I; H# I
  38.         public void ProcessRequest(HttpContext context)6 W% z+ N$ P/ d+ N$ c' m' z
  39.         {
    * r4 N' l/ y8 y* [
  40.             //context.Response.ContentType = "text/plain";
    4 x. N/ y% g0 E4 r- S2 ~
  41.             //context.Response.Write("Hello World");
    . ~5 d1 r9 Z2 H' p; B  y8 P
  42.             if (context.IsWebSocketRequest)
    , E) u1 d" e% `5 w; ^' Z
  43.             {
    / h9 z$ V- Z7 S0 _1 x
  44.                 context.AcceptWebSocketRequest(ProcessChat);9 ?/ T1 z; J  |4 u6 x3 d5 u, c/ r
  45.             } 3 y# Y8 o  ?! ^) b% }3 A5 b
  46.         }5 h# G/ ~  M! _+ H3 w

  47. & O2 |  M/ ~$ }3 y, X+ c
  48.         private async Task ProcessChat(AspNetWebSocketContext context)  }. b/ R& b; P2 \* I5 \
  49.         {
    " H- U( k# y' T6 W; s
  50.             WebSocket socket = context.WebSocket;
    * r: l8 A1 F5 G  z* G/ D6 L* K
  51.             string user = context.QueryString["user"].ToString();
    ' A6 B& u% `2 ?

  52. ; O7 t3 r2 O2 X1 D7 M
  53.             try8 ?+ \, p$ X& t  T- h
  54.             {: z+ y- l7 s( V0 F/ }: u" e
  55.                 #region 用户添加连接池: D( h+ n7 \8 {% Z
  56.                 //第一次open时,添加到连接池中% L( N4 ^; |! P/ D% h
  57.                 if (!CONNECT_POOL.ContainsKey(user))0 B# o0 t" S9 N7 C# l
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
    ' v# G3 u$ D1 d9 Z& S, A7 m; c3 g
  59.                 else
    ! y3 L0 P. H: v6 _2 K) D' \/ D
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ' P" Q: {0 I7 y: M4 a( c2 T
  61.                         CONNECT_POOL[user] = socket;
    , M! P% c+ e+ n9 G& w; e
  62.                 #endregion
    7 V. a/ B5 Q, s

  63.   F) ~6 c( v4 p+ E/ h( @
  64.                 #region 离线消息处理
    4 y% F. k4 p! }) r, D- R- r2 e
  65.                 if (MESSAGE_POOL.ContainsKey(user))4 O1 ~! `+ w& \! m2 W. U) J% \
  66.                 {
      i# w+ i7 o3 t9 O, j: h
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
      G( }3 Y$ E, R/ _, h
  68.                     foreach (MessageInfo item in msgs); b8 L) P6 ], e7 o2 j4 ?4 E8 o
  69.                     {/ o% N+ |2 u8 N+ E1 Q0 u
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    ! Y0 Z- i+ K/ p+ `$ ]4 r0 T/ d% c: X
  71.                     }2 o( E* o" C- i1 b  @+ t( W  X
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    ( q' ]9 h- w0 G  ]6 [$ K& d
  73.                 }
    9 R; g& E" T! `" [
  74.                 #endregion
    ! f. N. e' l4 }. {8 |2 z8 ^
  75. $ b5 S' Y! \! c$ M* P
  76.                 string descUser = string.Empty;//目的用户9 V- v3 E& m$ P  ?8 q+ a: k* w
  77.                 while (true)
    ' V$ \/ C4 d6 h% v* f! c/ }5 J
  78.                 {. \4 X+ A0 m( h
  79.                     if (socket.State == WebSocketState.Open)
    , B+ J5 W7 V9 I
  80.                     {
    . u5 A! v4 P3 l
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    4 S7 @" s1 R% |$ [/ A' K5 x8 U
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    6 S2 i- B5 i1 T( _/ |3 [5 s

  83.   A& H; I8 v% n5 [+ A2 i
  84.                         #region 消息处理(字符截取、消息转发). f. w  b0 `  }! d* l& b: p
  85.                         try5 b0 V4 H6 O* z& v# m
  86.                         {5 J$ y, b3 y2 I) Z" W
  87.                             #region 关闭Socket处理,删除连接池2 V+ G/ \. _) _, f
  88.                             if (socket.State != WebSocketState.Open)//连接关闭2 a3 E/ r$ \/ o: I" z
  89.                             {
    2 |5 ]& p  k+ |% [3 i' {
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    . M. Z: w4 f5 f6 T8 Y7 {9 B
  91.                                 break;" F: s/ k/ G; i/ [3 S$ Y, i! G
  92.                             }
    + B$ R+ V3 a7 B% O  r' |# u7 H
  93.                             #endregion( ~: H7 z( [* S
  94. " M( H  e8 A& u( k' L3 P
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
    / S; U, a' _. n& u7 W
  96.                             string[] msgList = userMsg.Split('|');5 S& i& G% C+ D( |/ m" [1 i+ q
  97.                             if (msgList.Length == 2)
    4 g  A, }& i. _
  98.                             {* p- A" l7 C  K: A5 [  H- {
  99.                                 if (msgList[0].Trim().Length > 0)
    ) F- [) i) c5 H. ^; ?1 ~
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户* j$ h) S$ W/ a0 A% F4 i
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));, C! O+ [% B2 v" c- g
  102.                             }
    7 n  S- {4 J* b6 t- ?, n7 [
  103.                             else
    1 z; z9 g, T+ a( y7 n% F' @  ~" w" s2 F
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));0 d: {; z, ~1 `+ {# W. D2 J/ ^  M# f

  105. ; ?* K: A9 q5 D- o) _& y
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线$ ~0 p9 Q6 p8 G  x9 T3 j6 ?/ ^
  107.                             {
    " b5 ^  p( ^' c! B
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ; B1 ]9 O- d6 h, |* `
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    . v/ T% u4 u$ t% F1 }4 K
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);8 D, c8 ?1 N6 i* s0 l8 ^: B/ ]
  111.                             }6 L6 Z" [& c) z0 K- a9 p0 ]
  112.                             else/ \" Z( n. X1 p
  113.                             {& B1 D4 Y7 a4 r' z- f* o8 {3 }
  114.                                 Task.Run(() =>
    $ r' ~3 t* h1 r5 g
  115.                                 {4 s5 b5 O& n0 g6 J
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中, r$ A! l0 _0 x5 h$ a) \# v! u6 h
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    , A( g3 h2 N& [5 g
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息/ C" o; N. A  B2 i0 J' i- E
  119.                                 });
    6 f# Y# b+ h% E( X& y2 a
  120.                             }7 P) i$ ?) J3 {
  121.                         }; b" H, G& g" s
  122.                         catch (Exception exs)) P+ d. I. V! S  @8 f
  123.                         {3 I4 B# C; k7 Y- ?. m+ a
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    7 w$ o$ H5 l  k9 X' A8 t$ p! x
  125.                         }' s5 X) x* T0 v" c( m3 m  T1 h
  126.                         #endregion
    + X# D3 p; d! Z# Q
  127.                     }
    ( }' E& Z7 H7 i3 W
  128.                     else& M6 S+ y" q# D. ?: Y  L7 [
  129.                     {
    ( i6 ]& [; d$ S1 ^
  130.                         break;
    + Q& P" O! ^/ I& ~! S  J
  131.                     }
    7 O, u& n5 C# b9 H/ w4 H+ A1 _
  132.                 }//while end% H7 m# N: E  C( {; D
  133.             }
    & o2 f6 U6 i& Q0 l
  134.             catch (Exception ex)0 h4 N. E, ?, n7 d9 ^" l7 K
  135.             {, ^) w* r+ W) e/ {
  136.                 //整体异常处理" f3 p. l/ k- }6 i) [: \
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);+ E- m7 X% |/ `- X: ~
  138.             }7 [$ I5 k. W7 |: s+ [6 I0 Q
  139.         }0 ]0 x5 v* D7 k* b) i* J

  140. . l# g0 C: A) w1 l2 \' |: r; i

  141. 0 W$ |9 ~- G) R7 p; j$ |$ q
  142.         public bool IsReusable% ^. g9 `, @6 N4 t# J8 V! l! q
  143.         {
    * v+ V8 j# J3 O  L# R: r" Y2 O6 A
  144.             get& j! m' r+ x+ r: {
  145.             {
    & g/ T, g6 t, z8 L" `& f" w% r+ o2 W
  146.                 return false;
    1 G( D7 z! A/ o! e2 i( `
  147.             }* o* A$ U/ C* a1 \+ O) G4 N
  148.         }, r: W. q9 a) m( H6 Y/ K5 B/ a
  149.     }0 B/ N9 H/ b' D; h# W, H6 k4 y
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
  {) y7 r- I" E8 U, _  n! U
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 20:03 , Processed in 0.118213 second(s), 22 queries .

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