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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
. o$ N' j5 l7 w! N+ {
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;" w6 Q+ Q4 v7 C! f% v
  2. using System.Collections.Generic;9 x. q& d- e# p0 v$ Z0 P; E
  3. using System.Linq;2 s3 {) _; o6 n* h) [; p. c' s
  4. using System.Net.WebSockets;
    $ d/ Q/ _) P# b2 {
  5. using System.Text;
    % w  N8 ~4 C$ T5 H$ ^6 p
  6. using System.Threading;
    " e2 p' t; G) S9 B0 z' f! ?2 w
  7. using System.Threading.Tasks;
    & X) o: M  G! w+ ]# }+ Y- m0 ]
  8. using System.Web;& F5 {3 B( o9 r/ r8 v
  9. using System.Web.WebSockets;
    : e7 E) {* P& E( I9 T
  10. 7 B6 Q/ v, S- s: E; h4 B4 y
  11. % z$ T" _  b: x3 P) t( i: P9 n
  12. namespace WebApplicationWebsocketHandler3 f5 C2 p; ?! p# [! }
  13. {' _( ]1 ]9 Y7 Q& \- B
  14.     /// <summary>8 p4 W; I3 F8 [2 v1 ]% A! E
  15.     /// 离线消息# ]2 W. j- L1 Z6 _9 I, Y$ Z
  16.     /// </summary>
    : H& z9 p/ Q! ^- V* s0 @
  17.     public class MessageInfo0 r+ h+ s& ]+ ^* T" N/ C
  18.     {  C. h5 t' t6 e$ X6 B! t+ W5 w
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    + Z, |2 b7 K8 L" N" B& `
  20.         {
    " B/ o0 C. v) @- [
  21.             MsgTime = _MsgTime;* D; H; i$ y% u( T4 I' b  D- k& C
  22.             MsgContent = _MsgContent;- H! M/ H) j- y% q3 T
  23.         }% w1 @/ Y: W; `% S+ p) u0 g# T2 @
  24.         public DateTime MsgTime { get; set; }4 z, R0 L9 `4 R1 C& g; Q; G
  25.         public ArraySegment<byte> MsgContent { get; set; }
    9 ?. [" b* I4 _. h/ n
  26.     }
    ' x/ q1 m! e; P$ z3 e% z0 S
  27. $ ^5 ]$ N/ r8 a9 l5 G

  28. 0 \) y6 {! B2 n

  29. 9 {, O# _5 G2 P8 W" h5 Q
  30. # A  p, @5 D6 _+ N
  31.     /// <summary>
    ( B4 }8 W: H. v/ [7 i  V
  32.     /// Handler1 的摘要说明
    . T1 }: g# c. W' [) z
  33.     /// </summary>, Q6 @# s1 g5 [2 c2 G& h% Z: X# D, P
  34.     public class Handler1 : IHttpHandler
    # e7 V0 \; i3 L. P/ y
  35.     {( C. z2 Q( Q; c" ]/ r/ h
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池- U6 }% _% Y  l$ \0 p$ h
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    $ R, a% w) G+ N, W3 T
  38.         public void ProcessRequest(HttpContext context)
    ; |9 o, i( Z" o' h" M9 I1 p0 e, f
  39.         {
    % u: l# X- ?7 k+ `  x
  40.             //context.Response.ContentType = "text/plain";
    9 W! D8 ]+ I) p( w9 M# I& W: v
  41.             //context.Response.Write("Hello World");6 l6 S! y8 D5 }+ [
  42.             if (context.IsWebSocketRequest)
    5 N: Q4 p1 c$ u7 _! D# \
  43.             {2 ^0 {  j- g! |# i8 p% ?
  44.                 context.AcceptWebSocketRequest(ProcessChat);. X+ N% m- S8 w% ^- X& O, h: J7 u
  45.             }
    % ^$ b( m- k* A: H. S# Z
  46.         }: F( J4 L4 [4 {! Z, g' D

  47. 7 s) U; {# c1 X8 R, k
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    6 {+ `# ]- }! u! w9 i8 a
  49.         {/ b* u: Q6 ?/ Q. N! K$ i( v' J+ S) n
  50.             WebSocket socket = context.WebSocket;
    6 V: D9 l+ d/ q) c0 e- @- ?1 {; V
  51.             string user = context.QueryString["user"].ToString();: [" f$ n+ U5 u7 ~9 L( D1 L4 k
  52. - h# u; R1 \& t$ e' k/ O( d5 ^; r- g
  53.             try
    5 V/ P' u4 ?2 t( x6 Z4 P
  54.             {
    7 m" h' O% y4 c! q, n/ l
  55.                 #region 用户添加连接池
    . ^/ X9 S/ l( `0 ]
  56.                 //第一次open时,添加到连接池中( F( {$ g. N- Y" ?# s4 F+ H
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    . O- A+ r8 X" U. g: r1 v* D
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加: Z% `" `( `8 A9 m
  59.                 else; V8 m- b5 A1 ?( ?
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新8 ~2 Z: ~# m9 b$ }4 L* K2 C
  61.                         CONNECT_POOL[user] = socket;- f& e# b) M" O9 l# T2 P
  62.                 #endregion4 F2 s: e) B5 Q8 {4 P
  63. & _( u8 V! }# Q! [3 G
  64.                 #region 离线消息处理
    2 \1 n4 o3 H8 \6 Y' n1 r7 h7 r
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    % S7 @( w' L! r* z' c8 i
  66.                 {# Q1 A  k, z* ?6 O) [% ?
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];7 F0 r9 d8 h* ~; Q
  68.                     foreach (MessageInfo item in msgs)2 W6 ~9 P. M' Q( H
  69.                     {
    0 Q2 z% k- B3 C& @$ o7 `! ]5 q
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    " ?) u5 d/ e/ [9 f+ o) |( j$ x4 G
  71.                     }
    . a0 }7 z* L6 X6 S$ P
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息2 X  c* G  ?2 b( u: \/ B8 T/ }
  73.                 }  C. W$ B% @4 V+ ^1 @4 ~/ i! D
  74.                 #endregion
    3 K- _- `0 u7 ?3 z. G* ?2 B
  75. 2 n0 l* _* u# d/ H6 B5 p  @
  76.                 string descUser = string.Empty;//目的用户% f6 ], `0 a* j& t. J0 }* h
  77.                 while (true); ^+ g* ?- m& h1 y6 C
  78.                 {
    ! c4 x% r- z, E- H' U0 o( N9 ]
  79.                     if (socket.State == WebSocketState.Open)
    + I& p& k, d& I4 t7 @- g) \9 Q/ s
  80.                     {; m. f5 \, I" B8 D9 d$ t+ b  v+ C; U
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    3 J3 Y& m( ^4 {  P
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    : N2 E4 ~; {1 `

  83. $ t6 r. B+ I; ]) R2 o8 w& D. Z% e
  84.                         #region 消息处理(字符截取、消息转发)
    8 W3 X+ w0 m$ T" O
  85.                         try
    - j9 ]! p  u* D* f& L
  86.                         {
    : H; X$ i/ A& E9 ]
  87.                             #region 关闭Socket处理,删除连接池3 r. C8 f. P' A& Q, T- z) M- k. T
  88.                             if (socket.State != WebSocketState.Open)//连接关闭% P2 A) ?' }, W5 x! l
  89.                             {
      S- [$ Z1 ~4 t- x
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    . b' }! `# g- O. O8 u8 s
  91.                                 break;
    0 T2 n+ v8 i& _. x/ f0 o5 x9 i
  92.                             }- X& J5 f. J- y  r
  93.                             #endregion
    * j0 z6 G* `$ I

  94. ! t5 n+ k& n5 y' }& F
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息$ ~* h, x) ?1 \$ B- ~
  96.                             string[] msgList = userMsg.Split('|');1 [" q% h& n' \5 v
  97.                             if (msgList.Length == 2)4 r; V; z+ A+ [
  98.                             {
    9 E! J3 T+ h- u
  99.                                 if (msgList[0].Trim().Length > 0)
    $ L; }  V+ `  d  Z
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    3 a: h- I3 N8 Q0 c2 T+ z$ m2 g' k  `. U
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));7 k! o7 ?" N( E7 F
  102.                             }
    ( p+ G  z) f* D- ?' W# c! b
  103.                             else
      ^9 E& I" e) l1 `
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    0 s  I2 A' F/ F8 x7 I  Z+ q& Y

  105. + K* j, g# B3 v
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    5 l/ [) ]) W9 s6 R" D9 Q, a% r" X
  107.                             {
    / `+ H' u  D# v9 r$ g
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ( d% G8 e! r5 q2 Q, k
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    7 a, |$ {5 w$ I, X
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);. d% N8 Y/ v, i6 A( Q% h- X7 s
  111.                             }/ L9 ^: {3 t4 Y5 U# Z0 n
  112.                             else
    , _; |& ?6 R' h  N8 P+ m+ k7 d
  113.                             {8 A( w  n, G( b; m0 v0 i& P; u
  114.                                 Task.Run(() =>3 s  \$ k7 J% ^
  115.                                 {
    % \9 G: a+ L5 Y
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    # z/ f& b. f- p. M4 M1 S  M1 I
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());& e8 ], @0 Z" `) ?3 }* ~, \
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息/ g- i  }7 D6 P
  119.                                 });  X3 Y) J- w% ^. x8 ]' `
  120.                             }5 W+ z. p8 g; h- \
  121.                         }
    3 j; X" a9 U9 h, n
  122.                         catch (Exception exs)) R1 v: x% e1 T* J. Z5 m! u1 R
  123.                         {- e. z* a# B. D! C2 @8 ^/ N
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    # Y8 k7 v. G/ y: m, V
  125.                         }5 q: @+ ?+ D4 x1 x! L' g  r
  126.                         #endregion
    1 ?& C' f! N) n0 L
  127.                     }
    5 ~! k8 W7 X  W
  128.                     else) V$ Z8 F% w6 y/ K3 }3 V
  129.                     {
    8 M& m6 R( q1 m+ A( O+ y
  130.                         break;8 d" |& l8 M) U
  131.                     }
    & M% C" J5 v- u4 M) @; d. L! E0 w: d
  132.                 }//while end; R3 a! D& w" U! w% M* Z% V* ]
  133.             }/ T( r' T* t' a) m# O
  134.             catch (Exception ex)
      `" {2 A  z2 a. b! |
  135.             {: t6 r9 ]1 x, C, j% o1 T- J2 h  X) e
  136.                 //整体异常处理1 k$ o2 W" l$ P+ R! o) f% ^' @
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    0 q6 N& ~( H$ R  }/ c
  138.             }
    9 g4 z% u/ u2 u/ M# M8 l3 Z$ ]
  139.         }
    1 C" M7 \) `/ [! m: L" V- u/ Q) H

  140. 2 t1 s% i4 X& a& ^, V1 D$ k

  141. ! R/ V/ u  g. [/ A7 s* I) N0 i$ @* I7 W
  142.         public bool IsReusable! X# s. ?: l, Q$ X5 y2 f; C
  143.         {
    5 i) T+ [: O. f% O
  144.             get. y' W3 N$ _8 {1 Y( w& q' R9 X
  145.             {3 ?' m4 @  }% _8 o! L2 M1 C
  146.                 return false;
    9 T% g3 x; ?. F2 p- {) W" j
  147.             }" `" I) E5 r  d; L% c8 n3 @6 u: f
  148.         }
    & x" r9 }/ l: ^, ]9 E' ^2 ?4 v
  149.     }( U7 B& G  g) M8 c3 d+ Z4 ~
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
% E5 M2 z* _' g/ Z7 B* y! O
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-5-18 19:41 , Processed in 0.122686 second(s), 22 queries .

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