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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
+ q1 y' p# Y1 ?  E
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;9 Q0 V( _5 ^1 h8 v7 ?
  2. using System.Collections.Generic;+ H9 q6 y- S+ e" Y8 z
  3. using System.Linq;
    ) t+ k" W9 Y) q& x7 X+ ?7 e
  4. using System.Net.WebSockets;
    2 b% X, y2 K( P7 R. m
  5. using System.Text;2 ~" A3 Z. r! \6 l6 v
  6. using System.Threading;
    ; n) C. c6 o- n  x3 d' C0 h
  7. using System.Threading.Tasks;3 P0 |2 O; R* Y0 a9 m
  8. using System.Web;
    , t) Z2 x8 m3 O( C
  9. using System.Web.WebSockets;
    7 @  v5 a/ H4 d5 E
  10. " o& _. G5 A! u
  11. 6 i, ^- t5 R2 R& Z: G4 b: _
  12. namespace WebApplicationWebsocketHandler
    + ~8 f5 P3 ^* N
  13. {2 u2 ], V+ a' `5 ]/ B
  14.     /// <summary>4 Y4 X2 c2 A+ p$ d. _5 Y
  15.     /// 离线消息- X9 q  Z/ d! w6 `6 L+ `6 G% T6 f, X
  16.     /// </summary>0 c" X; g* ^' P% t# @4 x
  17.     public class MessageInfo
    & B9 r  K5 Z# D
  18.     {
    $ H6 U# L7 z  q1 Q2 A1 ^/ m. Y! m+ k
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    / A, A; H6 B" Z) Q7 I1 {
  20.         {" \  g5 X# R& V: |3 q" `' R4 K& _5 w9 F$ [
  21.             MsgTime = _MsgTime;+ P9 ^' t; F& c+ N; n, J9 {
  22.             MsgContent = _MsgContent;! r: r5 M+ P) z
  23.         }, v: b( Z5 S5 H$ T* W
  24.         public DateTime MsgTime { get; set; }9 `# c  Q% q7 a) b2 \8 e
  25.         public ArraySegment<byte> MsgContent { get; set; }" d, {9 i$ V$ U) ~  ?
  26.     }
    2 k$ ~8 I' Y1 O! W: Q

  27. : e+ Y8 |3 I# k; ?8 F4 C$ ~3 @  k

  28. * M  L8 W  C3 ]  s6 k; D
  29. - }1 d: V* [7 G: J
  30. , i0 U' B& q8 [5 y6 b5 ?  [' V
  31.     /// <summary>9 \1 V  r4 p/ q, N
  32.     /// Handler1 的摘要说明
    * U3 Q6 N! B2 @6 g; S% }# S+ o
  33.     /// </summary>
    : ?8 Z6 p; V0 M1 `! c
  34.     public class Handler1 : IHttpHandler7 A# G, u2 ]6 N$ `6 c
  35.     {
    4 p0 C) v8 e( ~2 f1 D
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池' k" F5 ^8 k# R2 j
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    * j$ S5 f8 E) j, Q4 c
  38.         public void ProcessRequest(HttpContext context)( C; W& f' C; Y( h0 G  [
  39.         {
    , N# y4 G; e* ]2 {+ s! ~
  40.             //context.Response.ContentType = "text/plain";4 y. o0 u- Y/ y
  41.             //context.Response.Write("Hello World");' {$ Q6 a' S  q  ?6 o4 e" O+ Z
  42.             if (context.IsWebSocketRequest)
    " e# G1 h7 V6 V; u* B
  43.             {6 E. m! h% C/ z8 E: g4 W5 E- D# H
  44.                 context.AcceptWebSocketRequest(ProcessChat);6 U$ w0 j, H" C1 ]5 E9 a  j, }
  45.             } 0 V. ?( O7 x$ {- W+ j* o9 e
  46.         }
    7 V1 A: g( K! [
  47. # r6 `3 S6 [) w$ A) C; T7 {" [2 ]
  48.         private async Task ProcessChat(AspNetWebSocketContext context)& d" B2 o, b# T' U3 w; O' \7 Q1 i  p
  49.         {
    0 }3 Q7 J3 D/ U; c& c% L, |
  50.             WebSocket socket = context.WebSocket;" V( x! U2 g! _
  51.             string user = context.QueryString["user"].ToString();( [' Z6 v, Y; k/ Q, R+ D
  52. # D) s' m: e6 n3 N5 w
  53.             try& {+ @1 K# }% ]4 M+ N
  54.             {: x; A/ ^; Z, G/ e0 I
  55.                 #region 用户添加连接池
    7 K5 i( H+ X5 |2 }
  56.                 //第一次open时,添加到连接池中/ L- |# K  A1 Y4 s9 }% R
  57.                 if (!CONNECT_POOL.ContainsKey(user))* t+ V5 t- L# I  R7 b
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加
      p, B0 w, u. R6 l8 W
  59.                 else8 w$ A+ |1 J, }( f( z
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    ) C/ s2 \6 \* V$ h; a; c
  61.                         CONNECT_POOL[user] = socket;6 O# n! w1 |! C
  62.                 #endregion
    , k8 ?  i4 g* s# s! \
  63. ; j2 @& v  u- K3 b6 a
  64.                 #region 离线消息处理. x- k" \4 y% h
  65.                 if (MESSAGE_POOL.ContainsKey(user))3 ~& C' \( w$ W) f( R
  66.                 {0 @$ N+ Q% {2 W. g* u
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    4 @6 }: f4 m7 w) v, \7 p8 Z8 D
  68.                     foreach (MessageInfo item in msgs)
    ) T/ p& C/ C4 ~0 b
  69.                     {
    6 O. W* |( Q0 x
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);$ j7 b( b6 `5 e6 L5 W, C' w% ~
  71.                     }" \; k. R. ]! E0 J" h, A  w$ ]5 N
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息! q/ ]* Z  A7 Y* \( {
  73.                 }5 d* q2 b" R( e! X6 @
  74.                 #endregion+ v; m% ]" t6 ?1 N- D

  75. 6 @& A/ l. S+ {! i6 w4 b- s9 N/ a
  76.                 string descUser = string.Empty;//目的用户, P7 r) v9 Z) f7 S% [
  77.                 while (true)" d+ y) ~' e3 Q8 |( W$ Z+ g( y$ I, Z
  78.                 {
    , {5 b# h/ J: u* j
  79.                     if (socket.State == WebSocketState.Open)
    9 I7 c; _7 H% g# ?6 `1 N4 m, c! \
  80.                     {
    8 Y% j' P1 n$ Z  k' v5 @9 H
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    / n4 k1 Z1 A) ], s% N# c, k
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);& q$ x" @7 T- L9 g: `
  83. $ I8 I3 N' D' E9 W
  84.                         #region 消息处理(字符截取、消息转发)
    ! ]8 ~5 Y+ j; Z! a4 e8 M/ K' t
  85.                         try$ l0 E. b4 ]# a8 F' e3 Y4 V  b4 j
  86.                         {
    : V) p: m1 b/ }" w
  87.                             #region 关闭Socket处理,删除连接池
    0 d% G1 E6 k1 F& P5 o- q8 J
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    ( P# k' R9 h8 R8 J6 j% {
  89.                             {
    . m/ m/ J( k) R3 s
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    " q/ j3 X2 W) w  j
  91.                                 break;
    2 b* S# J' G* K% q3 C
  92.                             }- K5 x  Y- F! H+ T% D; h3 H! z! I+ F
  93.                             #endregion
    $ s+ x- y- Z1 r# S* r6 h5 v
  94. 2 A- k: B0 z, h# O
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息5 h& t& @2 H( K- P8 F6 Z  W, ]0 N
  96.                             string[] msgList = userMsg.Split('|');  [: s! ~+ A9 H/ x% D4 w
  97.                             if (msgList.Length == 2)# S8 ~( T& R7 a: Q  f1 {
  98.                             {
    ( H0 I6 @  |$ K$ [. \  |
  99.                                 if (msgList[0].Trim().Length > 0)
    7 g" `: u. S" U
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户% ~0 u$ e0 p  Q& ^, s
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    9 }: y, L7 Y; }. v1 n5 {, [! Q9 H
  102.                             }
    & |: C6 z2 w' V# W4 K- ^
  103.                             else
    ) o5 m7 ?: J* e1 c7 F1 F
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    , ]& |  y5 h) I9 F5 ?

  105. ' g) u+ d( `8 y! ?
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线: a% M: P  i* j' G4 J. E
  107.                             {7 }2 @: q' Z) e1 W. b
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端8 B8 W4 X  |0 }2 w% @9 b: O
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)5 _5 X& R6 D0 ^
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);0 L8 o2 @  ?9 r& F7 \
  111.                             }
    : J2 |7 m" ?3 ~: M4 i: E
  112.                             else6 \" b# m6 K' k/ m# R- {
  113.                             {
    / P2 i3 _  s$ |& Q
  114.                                 Task.Run(() =>9 d0 ^& G, E/ u6 L0 Q
  115.                                 {7 L3 a, p; |( Q) P$ U
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中) E4 I7 ]$ |+ }3 f( ^
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    6 U1 s2 |& q' s( \' F7 b
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    5 g/ _  g* s$ l: u1 G
  119.                                 });- f( S! T) N: S# K: m2 _
  120.                             }! z" f! ^% v6 ?
  121.                         }
    ! T1 A- Y, q: o+ N: ^0 h
  122.                         catch (Exception exs). m: H, g( o* E, N1 W
  123.                         {6 `4 i" H/ b+ {. [
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息' b& c1 K/ j% X: n- N
  125.                         }  ?9 V4 R4 h$ n6 u( W
  126.                         #endregion) n1 g8 t0 {" A& W, @: Z( T
  127.                     }( P8 ]7 m4 b8 s& Z8 U6 c$ A
  128.                     else
    ! n0 C. {5 L5 N
  129.                     {
    " Q6 D/ Q( G2 c9 ]9 g+ x  A
  130.                         break;
    9 l. v2 `" V  G+ w: Q6 J' {' q' n
  131.                     }! }- {/ x! ]9 a2 X4 D5 A5 V8 G  S) y
  132.                 }//while end
    + p5 A2 v$ X9 ~1 ~) n7 m* U% g+ `
  133.             }% o8 i& G3 L" x- s9 M7 G, j
  134.             catch (Exception ex)
    " e0 _# e+ h; \3 ?
  135.             {( G4 z( B+ r/ I( z
  136.                 //整体异常处理) p  X5 X! S9 z' [5 }
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);0 v/ F8 G$ t! b2 p# p0 g' I
  138.             }
    ( M8 E  E' s/ r! W4 i
  139.         }
    - u8 G. B2 m# v% g

  140. / n3 k) I6 ?7 H
  141. * |2 L' A5 C$ e: k, r$ m2 K! t
  142.         public bool IsReusable
    * R. ^* y: `( b' w0 |
  143.         {* q9 g3 d( x* h$ a6 A
  144.             get
    9 L# {. u: T  H# D# x7 ]
  145.             {2 Z6 ~1 R* J- B
  146.                 return false;& }  }! ?5 s/ f: Y8 y7 ]* s
  147.             }; H! g9 W, @0 z! D9 L
  148.         }
    : y: H8 o8 P* ?! a( j$ Y
  149.     }
    ; E/ q$ p/ B4 ~7 N+ e; ]
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

- G4 k5 \7 {. K) W$ `
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-8-4 11:35 , Processed in 0.061429 second(s), 22 queries .

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