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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

/ E% s6 f' t$ @7 S1 N/ S: L/ ~& o
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;
    , n9 b1 }3 T, g9 P; d
  2. using System.Collections.Generic;
    2 D; J& D) L" y9 M  ~
  3. using System.Linq;- J+ A  Y' K/ X& D1 s! X' \6 y
  4. using System.Net.WebSockets;2 u( u0 q! K: I1 T9 b. c; q
  5. using System.Text;2 m9 |& L$ V7 E( p) r# _! s+ j2 \
  6. using System.Threading;' v! L2 ?+ Y) m; m# Z
  7. using System.Threading.Tasks;( |( b4 S1 J" k: T) S
  8. using System.Web;) U+ l2 g- q1 ?% C
  9. using System.Web.WebSockets;. @6 a# |( W- P
  10. ! E# X, k, P  {  ]- r6 f. ?

  11. . _" E. b; [- [8 Q
  12. namespace WebApplicationWebsocketHandler" t' Y2 E, c% w: U/ d
  13. {
    $ g9 u' @  n+ [3 a0 L2 h
  14.     /// <summary>
    6 y0 |; W' |3 z: V
  15.     /// 离线消息
    $ C4 R) z7 D" R6 Q8 a" t) j
  16.     /// </summary>) t) k" d) k( i# v4 F) [) H
  17.     public class MessageInfo
    $ J6 }2 g1 g7 v' A$ F* F: [" z7 i+ _- L
  18.     {$ o3 k2 F  T9 B# ?+ ]! b/ e, Y/ ]
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
    0 J$ ?: o% d( g9 p9 I9 E# W
  20.         {
    ) W, d: E7 W- F+ P9 j
  21.             MsgTime = _MsgTime;
    1 x: f! T: e! d! k5 s5 K& a
  22.             MsgContent = _MsgContent;5 ]' O2 H% S- P- m
  23.         }
    * c, i, u4 @5 }  F1 q! y
  24.         public DateTime MsgTime { get; set; }- S7 L$ @! Q  W" R  X/ S
  25.         public ArraySegment<byte> MsgContent { get; set; }# S6 g# M7 l; O( I: `
  26.     }6 ~3 l& N5 ]3 i; o* L5 L, V8 h8 w

  27. 4 u- s5 C$ ]- ]) y# x
  28. * a3 M+ L& x+ G1 e) k- \
  29. / D) ?" [- m$ j
  30. 4 z2 ~4 O6 x( N8 {
  31.     /// <summary>
    4 k$ E* z8 K2 c9 E1 @  H
  32.     /// Handler1 的摘要说明
    : K1 d( z) s/ s( M6 }- d
  33.     /// </summary>
    8 g' v* u* B2 Z5 O8 I& G
  34.     public class Handler1 : IHttpHandler8 f# N/ L. d8 R+ k5 P7 O3 g
  35.     {
    1 j( B7 S8 g9 U" S$ m( q9 K
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池3 d" @% e* b$ _) o+ N3 y  ]
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池% p2 q+ h$ |3 A1 J2 t( z4 ?
  38.         public void ProcessRequest(HttpContext context)& t0 q, ?- F# F) M: x( T5 E4 y
  39.         {
    1 F- A+ R4 E" w: L+ c4 y5 k" ^
  40.             //context.Response.ContentType = "text/plain";
    , p! \. g: L; r, G
  41.             //context.Response.Write("Hello World");
    5 `9 g  f3 R8 C/ J0 D- g8 l# w
  42.             if (context.IsWebSocketRequest)
    4 c# K* X9 B# Z$ v. F) U* a
  43.             {
    ; g; x% |* w0 t
  44.                 context.AcceptWebSocketRequest(ProcessChat);; @: ^# N* o% k3 V) {8 ?: P: f. l$ R
  45.             } 8 s- X6 y- y' S+ C
  46.         }
    & F+ _* t4 u: X

  47. # m2 D: b! B' d" |- I
  48.         private async Task ProcessChat(AspNetWebSocketContext context)8 a; i7 H3 s* m+ x, [6 l) h8 Z
  49.         {1 r4 i. q% @2 |' C8 ~
  50.             WebSocket socket = context.WebSocket;' j! B2 V( Z9 R5 z. I
  51.             string user = context.QueryString["user"].ToString();) E9 A. o% g7 C; N+ w
  52. & ?7 ?) x" x" w, S( P
  53.             try
    - H2 n; H, A4 o# w6 q
  54.             {2 z6 V; x' a2 U9 N3 v  \, U
  55.                 #region 用户添加连接池
    , O4 n/ @3 \, L; B0 O, N! y
  56.                 //第一次open时,添加到连接池中
    ' C& w; t- P$ P' t' X1 m6 [$ V
  57.                 if (!CONNECT_POOL.ContainsKey(user))& w0 W1 l% B* E
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加& S7 D9 Y! h0 r% v1 W+ `
  59.                 else8 i1 m- K. g5 e9 ^0 W8 X4 l  v7 w! [
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    . i6 U( d6 I) z5 y" R, S
  61.                         CONNECT_POOL[user] = socket;
    4 }% g( R# N6 x. [) P3 p
  62.                 #endregion9 J! `' Q8 Z1 y
  63. 4 E1 n4 X. |. g& |7 T# P
  64.                 #region 离线消息处理
    2 t6 H0 F* @9 A: g. G& d+ |3 K; y
  65.                 if (MESSAGE_POOL.ContainsKey(user))
    ! z! w3 k$ V# I8 r  v, {( k3 r
  66.                 {- {8 L: _, o4 [8 K7 ?% J
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];
    ; W" ]4 C+ N/ T6 i* q
  68.                     foreach (MessageInfo item in msgs)+ h$ R0 e5 y5 o$ l
  69.                     {" ~9 w* v+ j+ K( q5 G8 ]7 J
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);, R, {2 r  N/ [* x) V+ K
  71.                     }
    8 C% x+ a( {# |( M" P1 M9 F; _8 g
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    5 N! s; J8 u; O4 x! v" k
  73.                 }
    5 n; Z0 Y$ B/ ?% L2 g
  74.                 #endregion
    . {+ s  w6 o, U
  75. ) a) j8 }# Q" \' h9 G8 J6 ^9 d
  76.                 string descUser = string.Empty;//目的用户
    6 Y% O2 Y& ]! r6 b& i( z% E
  77.                 while (true)2 ?0 v1 a% [) J, U1 Z' e  e+ Q
  78.                 {' P2 X% U: w3 c$ W* o0 q8 N
  79.                     if (socket.State == WebSocketState.Open)- I, n7 C2 J' [5 k( w6 ^) `9 t
  80.                     {
    * G/ U3 z. p4 f  E
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    , c( Z2 @. J, h8 w8 y8 P0 h
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    * s7 u+ p1 r- O' y3 A+ O
  83. 0 o) S# I9 }: E
  84.                         #region 消息处理(字符截取、消息转发)$ ^# e0 R' I7 V1 c- q
  85.                         try7 y' K* @, C: F/ f! @
  86.                         {8 k! b' S& B3 F: e+ V& {5 e
  87.                             #region 关闭Socket处理,删除连接池& A8 B2 E4 ]9 g- j
  88.                             if (socket.State != WebSocketState.Open)//连接关闭1 _: j$ R1 F+ \' r/ `, H
  89.                             {  }* }6 X, E. h
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    0 A/ @9 r/ L8 V% O8 j
  91.                                 break;6 A8 v1 W3 [$ A+ Q% e; q
  92.                             }
    7 M" N  w+ T; s5 c! a
  93.                             #endregion" `: b( Y( X6 U2 a! ?2 t0 B9 j; b# U# s
  94. ! j" F& [1 {+ [: V, g
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息7 h& r4 w- R/ |# c) A
  96.                             string[] msgList = userMsg.Split('|');' r# K# j* v5 T; [9 E: D
  97.                             if (msgList.Length == 2)( ?+ Q. d* ?. T$ Z* n
  98.                             {5 X- i  G, Q* G, ^5 E1 I
  99.                                 if (msgList[0].Trim().Length > 0)6 i" y+ ]' K, Z! {1 z  J$ w2 i8 m) A
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户4 _. L1 U* y4 j* w+ v
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
    + Z: g! {$ J; {+ F
  102.                             }
    ( v% y! F# r; O4 `$ A
  103.                             else
    2 Q8 L; ?( t0 o- ]$ s
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
    ! n6 D, G- B. b% ]2 Q; p8 }
  105. $ P7 I# G' z# W( Q# R: t
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
    : D# O, I2 t, Y6 l
  107.                             {
      v3 e3 F( r, S( ]: \  {
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    ' b( t2 Z& Z7 e6 D# [: Y. l8 u
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    0 X* z4 j4 ]3 N  G. n: B
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);- Q  n1 }. V% D7 l
  111.                             }1 m! W- z7 j/ ~. I
  112.                             else6 u9 l$ [- w$ l# ~2 v
  113.                             {/ m( U1 O, d' ~8 R; r' x( Y
  114.                                 Task.Run(() =>4 q8 L# Z1 w1 ~. D5 q; k2 A
  115.                                 {
    # _" d# {. }5 x7 O2 _
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中7 B4 R7 G  ^, P. P7 H' f( l6 l
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
    * r+ z( i* v; i/ h) X; L# \; a0 o, N
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
    - \4 f2 S1 M6 J$ U$ G
  119.                                 });
    ) \; D. I4 d6 d. v7 L
  120.                             }5 `9 I1 d. q5 |8 i2 J
  121.                         }
    ' K- z# p2 A7 _7 D7 z$ ?
  122.                         catch (Exception exs): s3 |8 S( r: j+ q/ d, ?6 b
  123.                         {
    ( F4 A$ t- j' j5 D' ?
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息3 b& _# b) S3 j5 B" A! Z
  125.                         }" l! F0 {" k" \1 T" h/ t
  126.                         #endregion
    7 U) ~% |- E7 J+ G! K" e
  127.                     }% O3 y# B7 f$ F* W5 ~
  128.                     else4 C- ~: N$ U9 l( f; d5 Z
  129.                     {
    4 k) m! f7 j( n/ Z5 W+ w
  130.                         break;
    9 ~% F" r8 B+ G# X0 k# a8 d* y# A
  131.                     }
    6 u1 u$ _. J& w8 t
  132.                 }//while end2 J( O% R1 R' t3 h! ^- `
  133.             }8 a+ R+ I! T% Y
  134.             catch (Exception ex)
    5 J, [6 Q' w$ V3 O  n/ q8 n. r
  135.             {5 i) F# N4 L, d2 Y# H( J
  136.                 //整体异常处理
    % |( D) B. {* `
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);0 T& Z7 R. L/ I* P7 [
  138.             }+ C5 i1 M" h9 Z
  139.         }
    ) l) h- }% r  K3 {

  140. ' f+ l9 M; x1 m; r9 b, R

  141.   h! m3 I9 A# F
  142.         public bool IsReusable
    4 ^/ m3 t( u- n+ a: C# ]
  143.         {
    5 o( ]$ K( H6 H5 L/ e  V& g
  144.             get6 S2 e$ z/ z( ?8 l% h
  145.             {
    $ r1 k0 p# f8 \" O, [5 b4 z: C
  146.                 return false;. G( Y/ _2 @2 o- e/ C6 ?
  147.             }
    , ]# R. T& G3 R) ]7 F; r+ z% s
  148.         }, Y; q5 `+ I6 X- Y3 ^9 {
  149.     }
    - d* F; \: G) e1 \- d6 s
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

1 M5 E8 i! K8 j& Z- Y
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 16:19 , Processed in 0.060224 second(s), 22 queries .

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