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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2018-11-7 00:43:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
服务器端代码编写
1.新建一个ASP.net Web MVC5项目

9 R4 s; x% ?- R) X# P0 j' X
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    & q3 Y" }) V+ o7 Q" U; K% N
  2. using System.Collections.Generic;
    9 U, A( M  F7 J0 W- z
  3. using System.Linq;% ?) ^. {3 E% J4 L. U
  4. using System.Net.WebSockets;5 v8 q' {9 Y8 [$ z
  5. using System.Text;1 T1 M; |4 Y* T3 y+ x. J0 g9 c
  6. using System.Threading;7 t3 T6 C$ N% z& u
  7. using System.Threading.Tasks;
    0 Z! q+ f3 u! O3 d7 d! ]
  8. using System.Web;/ J( l* x3 ?$ j2 C* p
  9. using System.Web.WebSockets;
    ! R+ P4 F9 s& |+ C6 k2 o

  10. . G" s9 T9 ^2 A/ \
  11. 8 b6 S; T, w: [) A% s1 U- M
  12. namespace WebApplicationWebsocketHandler
    - f$ K1 V6 q# T9 E) R' e7 i! e
  13. {
    8 K0 }4 i) O' V; n; b
  14.     /// <summary>
    % _. u4 v) i% l/ O- [
  15.     /// 离线消息/ S! S8 ^8 o, S+ [% B: }
  16.     /// </summary>0 o# D2 X% y, ~
  17.     public class MessageInfo
    - v5 j1 Z& ?1 F
  18.     {5 B5 |: H' ], x; K
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    1 p1 u% @: n3 {3 S2 }& Z' @
  20.         {$ O( C3 B2 H$ U, R3 r
  21.             MsgTime = _MsgTime;
    ! ]9 D4 T8 R+ t, \
  22.             MsgContent = _MsgContent;
    * h: }7 l/ S6 ]0 L
  23.         }. I7 z8 n5 g6 O. w  T, N
  24.         public DateTime MsgTime { get; set; }
    " x0 G, S" s# _4 s( c. M
  25.         public ArraySegment<byte> MsgContent { get; set; }
    ' X2 f8 L. Q) _4 C& _$ _
  26.     }; \5 s' f8 X6 [
  27. $ m$ G" T9 C0 O! J$ r2 |
  28. ; U5 @6 ~6 |4 w' l& C+ \: Z
  29. * ^3 o+ r' A1 U- s% l: A& C7 k' r
  30. 4 o! p: d3 i6 N/ `
  31.     /// <summary>; L% g: C" X8 j0 V& P
  32.     /// Handler1 的摘要说明
    - n" `, L" d' T$ i" r* ^8 {
  33.     /// </summary>
    ' O# Z; `/ o0 b  Z- ^
  34.     public class Handler1 : IHttpHandler
    9 Y+ P& ?8 A% m, h$ b: V1 T
  35.     {
    ; S' S: f7 j) D4 H' `% q
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
    , ]2 }4 [1 w- [. S" D
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
    7 U5 M1 u1 C7 u* c! t7 i: q2 U. G
  38.         public void ProcessRequest(HttpContext context)2 B$ ~1 \. O% N
  39.         {% ?, L  r3 V' I6 N; n* m: r( `
  40.             //context.Response.ContentType = "text/plain";
    $ Y1 B1 O; o: Y$ z
  41.             //context.Response.Write("Hello World");
    : m/ O0 Y3 @7 ~4 ]4 r3 y+ t$ Y% J0 R
  42.             if (context.IsWebSocketRequest)$ o, H* O# I' e9 h" ?
  43.             {9 o  @. H' z. q" l
  44.                 context.AcceptWebSocketRequest(ProcessChat);, l" ?0 B7 x/ |$ w; M: o: n
  45.             }
    6 Q) U& \2 s% I7 P; B
  46.         }
    - }+ X" l4 N. K0 N2 [5 j

  47. 0 j5 f( c0 |7 T! R2 L  j3 V
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    $ a0 Z- T$ w5 u+ h; e
  49.         {2 O7 D4 ~; o$ z- ^0 V) ~
  50.             WebSocket socket = context.WebSocket;
    8 K/ |/ m* \7 \, g% s5 e5 m2 r' x
  51.             string user = context.QueryString["user"].ToString();' K" X+ r, m+ [9 u8 |+ L% @1 Z

  52. * ?$ m1 R' T0 f8 Q0 S3 y1 O9 i
  53.             try; F1 A  I, X; i' D
  54.             {' w. z1 ~9 L; r$ |
  55.                 #region 用户添加连接池; {6 x* W: G0 V0 z. F3 X  Q
  56.                 //第一次open时,添加到连接池中
    ) i: \- ~- W9 w
  57.                 if (!CONNECT_POOL.ContainsKey(user))% G: w! n8 c5 S1 m2 M: [* u+ h
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加7 ~% T8 _( u) [# T
  59.                 else
    , V. F8 a- Z7 ?$ N# }$ k" l
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新1 c+ q6 {& a: a2 t, H! _( f7 O
  61.                         CONNECT_POOL[user] = socket;  K/ {8 P! [# v( [; L
  62.                 #endregion0 V7 e' X& _& R8 L% x
  63. 9 r  [: K% ]6 {$ B
  64.                 #region 离线消息处理' Z9 [7 a" f- r' E* k4 H
  65.                 if (MESSAGE_POOL.ContainsKey(user))" x# P/ S+ J6 ^% a+ E% x9 `/ O
  66.                 {1 |% Y" a' ?2 a1 G) s! o
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    7 i! E6 U+ m; J6 g; S9 z  ]
  68.                     foreach (MessageInfo item in msgs)4 `. P- _% e2 }% Z) R
  69.                     {
    6 _: M% U: u+ p
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    + ]( W2 |; f6 K* f
  71.                     }! N* B4 n8 N2 n, e7 f3 P$ s
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息% X! k) G" a1 O7 {
  73.                 }. u. v1 L/ n) W4 w7 C$ C. g
  74.                 #endregion
    ; s& C* ?( u9 f. O

  75.   y# Q6 c. u7 p: }" T" U
  76.                 string descUser = string.Empty;//目的用户  p! o+ ~! {6 `, S. m8 P; U
  77.                 while (true)
    : T& M8 F& W) n$ m, a7 N
  78.                 {. c, N2 A) ^+ v1 U
  79.                     if (socket.State == WebSocketState.Open)
    5 T" Y& `4 N( [% F0 F# K% N2 {0 ~$ [
  80.                     {& p* \% z/ w8 K- j0 M7 ^
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);# Q; C5 R8 [/ J: d
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    . R5 G/ x  _$ O6 P! k  q
  83. % Q# ~5 S1 [2 d7 n) u8 B. i+ E
  84.                         #region 消息处理(字符截取、消息转发)
    % G9 O: d8 Z5 r4 s6 T
  85.                         try$ `  M5 I8 L( g. R  O9 h  Z
  86.                         {$ B- [* [8 A1 L: ]# ~4 Y& `5 A
  87.                             #region 关闭Socket处理,删除连接池
    $ k3 c: z+ x, v( E, H) J
  88.                             if (socket.State != WebSocketState.Open)//连接关闭  K: ~# p; D& D" R' |
  89.                             {8 Q, H! l# K: i  F
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
      K+ o, }. V- h' y3 Q
  91.                                 break;
    * D, f% |$ s! y
  92.                             }
    * ?5 G: E5 M1 n; |9 N& H, M( w
  93.                             #endregion
    & j' N6 }, G6 R+ B" D
  94. & L5 s1 f( X, r/ `$ @7 S
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息3 O9 e- m+ S+ j5 }
  96.                             string[] msgList = userMsg.Split('|');% s" \5 C$ L" O1 Y* ^1 K8 X
  97.                             if (msgList.Length == 2)- l7 ]$ O: g5 y! u9 T. B; ~. D
  98.                             {2 {8 @; a# m, t( m4 o$ M4 b
  99.                                 if (msgList[0].Trim().Length > 0); Z; S8 m6 ~6 W5 u
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户$ d, k; k6 I) X6 _$ M( T6 F
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    # R; k; V- \4 T& G7 c
  102.                             }9 f0 E& X5 D5 Q5 x- m
  103.                             else' k' V. L7 v$ O0 s3 i# o
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    0 W" n+ I% u9 O3 q0 p  }, `/ Z

  105. 3 Q5 E$ \7 j7 ^  I& U8 ^+ r  K0 E
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线( k4 W) v5 ~# M, m3 N: b
  107.                             {
    ( z/ }; m) G- P6 f
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    " Y2 }- D7 ]) I1 T# D
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    ; \3 ?0 }/ `! R; H2 b( {! ^! `& k
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);0 a8 f9 [0 i; S: l, f: G
  111.                             }) l2 B# p  o9 v* @
  112.                             else9 X0 k$ s, W1 @' y* g! q4 X- s/ y$ I
  113.                             {
    . D3 E8 o2 V; F5 e( w
  114.                                 Task.Run(() =>
    0 g" k5 L7 W6 O8 q; Z$ ?
  115.                                 {
    2 U# Z* k/ p& s; z. W5 Z
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中# |5 |, \6 u7 h3 I- ~9 v7 @6 ?
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    6 n" J5 o$ y+ v" S* K3 I, T2 e# d
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息, e& x! z% w# c) h( M! x
  119.                                 });
    $ a4 d; w  W- P8 [: Z1 F
  120.                             }
    0 k8 x9 X" l! |; @0 {# X
  121.                         }
    8 m: {* {1 J2 q5 N" B
  122.                         catch (Exception exs)+ W' H- |6 u5 [+ ~% V3 s
  123.                         {: a& D( d2 f9 f% ^/ ]
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息0 n5 V( V3 T/ s% Y* J
  125.                         }
    : o) x3 V  I7 C
  126.                         #endregion. |& y  ~0 d* v
  127.                     }
    6 u9 z8 L" L% a9 X. l! D+ Y8 Y
  128.                     else
    2 y; f  x5 w3 H$ U  S
  129.                     {; K! _: Q# R8 c; k  r; Z% w
  130.                         break;: N/ ]$ I6 N0 ?3 W4 h
  131.                     }
    / v% C5 n: y! q9 l. p' q, ^
  132.                 }//while end8 ~' d9 A# R. x( |
  133.             }3 p, C2 _, c5 H5 u/ v* d
  134.             catch (Exception ex)/ E  u& ^8 h5 h* s4 E
  135.             {
    - g# `8 R4 \+ `
  136.                 //整体异常处理2 j8 E' u8 ^# A0 p& G
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
    " z' R& h3 q2 A. x) H$ J+ |6 Z- a2 `
  138.             }+ R/ c2 L# L5 k! @
  139.         }: W& |1 [0 _" E( s# d( S
  140. ; T$ N& }3 L$ J; d: m; f
  141. : m9 A1 n, _* `, i1 Q) {- i
  142.         public bool IsReusable
    , i! R/ \* V5 |0 f
  143.         {
    ! N" z, Q) k1 Z1 H; E
  144.             get
    . P: Z1 a+ C. @1 n+ L& G
  145.             {
    ! J- o. V1 n9 W  f
  146.                 return false;
    ( @. t+ R* V2 x! ?
  147.             }
    4 q) A; |. n7 G1 Q5 I# g- X* g
  148.         }
    7 T" g' l' ^/ K' z8 R
  149.     }8 s2 H* l3 ?# p* W6 J
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

6 A# R7 M; ^. n8 z1 u1 D* M
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 12:14 , Processed in 0.151625 second(s), 22 queries .

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