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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

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

  D- c, {2 \- M, {/ U$ T% y
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
  1. using System;( I+ S( z8 ^: O$ h# G( N$ T
  2. using System.Collections.Generic;! N/ C7 }/ p: J
  3. using System.Linq;
    ! e+ b  H+ h5 j; f  e; G; W, q
  4. using System.Net.WebSockets;; K2 I# K7 [8 {* [
  5. using System.Text;
    ! q* C3 ?& t: @2 ?! F/ T
  6. using System.Threading;+ P  F8 G  G( O( H  ]" _
  7. using System.Threading.Tasks;
    8 j& L4 V& U) T4 h6 Y
  8. using System.Web;
    . H5 n4 L4 M: _/ P: B
  9. using System.Web.WebSockets;
    8 B8 J8 K( D2 o

  10. . Y. c0 t; l" C1 Q, v

  11. # I  O- {  h+ E, s" }4 O4 e
  12. namespace WebApplicationWebsocketHandler
    % u; `: N/ t, O! R% F1 V$ r% ?
  13. {
    * P7 \7 M4 K4 n5 I
  14.     /// <summary>
    8 N, _% R% ?$ R- f' a* D, ?/ J
  15.     /// 离线消息
    6 T, P/ O$ `. G* a' Y9 J
  16.     /// </summary>9 x3 ?  l# c6 t1 ?& R, a
  17.     public class MessageInfo
    6 V2 d: F# |; B9 C
  18.     {- n( X1 t. Z" D6 M
  19.         public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)8 W: h5 Q  ?" k1 ^! Y3 v4 I
  20.         {
    / q! k/ j7 @& }" Y7 I
  21.             MsgTime = _MsgTime;
    $ L- }7 d- \+ ^/ B
  22.             MsgContent = _MsgContent;! g: g6 }2 h; ?; E9 ~
  23.         }! O" k# J3 x2 n" p
  24.         public DateTime MsgTime { get; set; }: x% E/ `; l0 |
  25.         public ArraySegment<byte> MsgContent { get; set; }4 N& n( a& m: X$ M5 S
  26.     }
    1 H- t, X1 G5 Q4 G* S
  27. ! y/ A' Q! ^6 v0 G; F

  28. 0 S% ^3 N: ]9 b6 W/ T4 \: G; ?
  29. 6 ?: O. U$ b- Y8 w

  30. . ^: ~4 E6 c+ Y( u6 ?' F; O. {
  31.     /// <summary>. w( A0 g- `2 A- R* l
  32.     /// Handler1 的摘要说明
    6 T; c8 r' k) I9 {4 m
  33.     /// </summary>
    ! n" T( c+ w- B, F( Q$ s
  34.     public class Handler1 : IHttpHandler
      `# K" i2 o2 C( f( k
  35.     {
    & _9 L: R0 `( R0 b' V( D! s# f
  36.         private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池/ Z: H& P$ I2 l& k4 A8 K2 S
  37.         private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池) v1 N5 Z& V6 R: Z
  38.         public void ProcessRequest(HttpContext context)/ O! ~+ I5 A3 u6 Y6 W
  39.         {9 o/ ~9 s1 Z: ?1 P$ @
  40.             //context.Response.ContentType = "text/plain";
    4 N( J. W9 C7 X# v3 x0 I
  41.             //context.Response.Write("Hello World");% d, I, I: G& |/ D) \
  42.             if (context.IsWebSocketRequest)
    $ b. z  ?- V" Q
  43.             {
    " m- ]1 U9 b7 Q' O$ U5 W4 T
  44.                 context.AcceptWebSocketRequest(ProcessChat);
    6 G9 |& Q4 n  y5 I. }+ A- }
  45.             }
    ( K9 o6 Q% {' J: ~' W/ N
  46.         }
    , Y# r3 H3 p; q  R) `

  47. 6 e" ~9 S+ c8 _4 s! X( s% O
  48.         private async Task ProcessChat(AspNetWebSocketContext context)
    . k( a+ z+ J* H9 \# R* h) {) z9 b
  49.         {* v& V2 O3 {8 G* N6 z
  50.             WebSocket socket = context.WebSocket;
    , B1 |3 N9 E* C  _1 g3 M
  51.             string user = context.QueryString["user"].ToString();8 V( C& ?! Y3 u5 ~* C! A
  52. $ s* ]3 {$ c" F- C: y# }
  53.             try
    ! W& c! @  @# Y
  54.             {
    ! n$ |1 x& Y# s
  55.                 #region 用户添加连接池
    ! L3 J" o6 H9 }* T4 Q. u
  56.                 //第一次open时,添加到连接池中
    , x2 k* N/ L9 H3 X
  57.                 if (!CONNECT_POOL.ContainsKey(user))
    4 S( @; ^, V/ \. S
  58.                     CONNECT_POOL.Add(user, socket);//不存在,添加% g! o& H) n5 i' N
  59.                 else& b' a6 y) i3 U/ r) z  w
  60.                     if (socket != CONNECT_POOL[user])//当前对象不一致,更新
    + y, X' H8 Z6 W% \$ }3 ]" E
  61.                         CONNECT_POOL[user] = socket;! r3 o8 {1 c+ \
  62.                 #endregion. N+ _, f. c$ {) }1 n7 M( L
  63. ! l% w' z2 \9 E( N) L
  64.                 #region 离线消息处理
    , I/ w. h" n* z3 z
  65.                 if (MESSAGE_POOL.ContainsKey(user))) `+ F0 a, U6 r
  66.                 {
    " y- V7 f+ L; C0 f/ _0 P& o6 @
  67.                     List<MessageInfo> msgs = MESSAGE_POOL[user];  O( T+ q( t: W' S0 L
  68.                     foreach (MessageInfo item in msgs)8 j/ F- I8 d# ~" u. ~+ `
  69.                     {, m/ T6 M9 c& |3 ?3 b: d
  70.                         await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
    5 b6 o/ h! i& l1 l( ^1 c: j5 \! L& m
  71.                     }
    / X2 A8 `0 b( }$ s- Q) ^
  72.                     MESSAGE_POOL.Remove(user);//移除离线消息
    " E+ |; K5 r1 O! O0 c
  73.                 }
    3 D; b! @- ^% U. F8 ]8 [
  74.                 #endregion' [: ~# Y6 ~% o
  75. % O. @# Z6 C' Y; {6 R' N& _& d" _
  76.                 string descUser = string.Empty;//目的用户
    6 |/ K6 R% i  o: Q; x
  77.                 while (true)
    , H; q& m/ |- V# M3 `
  78.                 {
    + |% ^, U; s* y, O0 _" f  U8 o4 B
  79.                     if (socket.State == WebSocketState.Open)  L3 V# H% O, H6 K# _4 f
  80.                     {
    0 ^  o: O' a" D' Z1 ^* Q& T
  81.                         ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
    , X& _2 d/ j2 I1 ^9 K
  82.                         WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
    $ d' u; G4 D# H% K4 x

  83. 9 e- R; s* l# i; M, T
  84.                         #region 消息处理(字符截取、消息转发), w! O/ J; F0 J$ `2 v$ w/ h
  85.                         try
    ; U# O# D, h  e5 [3 B1 q& C3 g
  86.                         {
    , c2 f! l+ \; ~
  87.                             #region 关闭Socket处理,删除连接池; @9 L% v1 X7 z, r$ [
  88.                             if (socket.State != WebSocketState.Open)//连接关闭
    - ^$ r# ]; j2 i  \/ h
  89.                             {
    8 X4 y3 i; z$ A/ a; u
  90.                                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
    , A& c. C2 R! d  o0 @
  91.                                 break;
    7 W: e9 X# l: m6 u0 r5 {* o& x
  92.                             }
    7 ^6 f: h7 A  y) l! M
  93.                             #endregion
    - D2 X) ^% E+ Q2 I( d- N* y0 W
  94. ' a% h! N1 B! e+ l1 K8 W7 F
  95.                             string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息+ Z: z9 R5 @! O% ^+ ?
  96.                             string[] msgList = userMsg.Split('|');* q' ]7 Y& c6 J1 L7 P
  97.                             if (msgList.Length == 2)& q& y" `: V# @1 B8 @) h
  98.                             {
    7 I% H( O' D$ {# o' F$ \
  99.                                 if (msgList[0].Trim().Length > 0); o/ Y1 _# M) ~" O% I# ^
  100.                                     descUser = msgList[0].Trim();//记录消息目的用户
    4 r. S- z# S. |, u+ P# G4 H
  101.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));8 ~' p& @: ^  O  O/ P
  102.                             }
    4 n* S9 h+ Z- V+ I$ a+ ~- c( x
  103.                             else! K! H  ]) z: f+ A- y$ Z
  104.                                 buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));: i# K9 H; |) @, g$ g

  105. ! O" U# F3 W* }6 q- h* `% t
  106.                             if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线! a2 C! O; x8 U2 q5 x; f, B
  107.                             {' S+ u& H  @& v
  108.                                 WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
    / F3 z) w3 x4 e! ]" L; [8 h* @
  109.                                 if (destSocket != null && destSocket.State == WebSocketState.Open)
    , `( D  K) g. \+ |
  110.                                     await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
    + a% G! D/ v3 ^/ t
  111.                             }$ {% J2 `0 }; n( b3 B
  112.                             else$ I! |9 Z. c1 A# m: Z' t
  113.                             {8 L) Q+ q9 P. Y4 i" F* S) g  q5 r
  114.                                 Task.Run(() =>& x' f" l1 w& \/ f" z
  115.                                 {
    : A+ f( j/ {* \! g% D" ]4 v
  116.                                     if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
    ) H: }7 j# N4 P2 O- h1 n" Q
  117.                                         MESSAGE_POOL.Add(descUser, new List<MessageInfo>());; S1 B% _. L* F2 x) h! ~& z
  118.                                     MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息% X: F" ^, |$ j. `
  119.                                 });
    ) \1 X: C7 c2 v( `
  120.                             }) s( w& J6 I  S: h- R3 f
  121.                         }: u6 s& T  E/ ^. L% W/ H9 h
  122.                         catch (Exception exs)2 l1 W- m. n: p& ~7 U. \6 C
  123.                         {6 \: |3 b- D$ [4 U
  124.                             //消息转发异常处理,本次消息忽略 继续监听接下来的消息
    . ^2 }2 o, T6 d  L) Y
  125.                         }) L* O  g: B$ J0 ^, }
  126.                         #endregion
    ( }8 H& d$ ^/ c
  127.                     }: a% _% C7 W+ O* a
  128.                     else( y1 C5 V6 h$ r
  129.                     {3 f* x) M' \: S" g4 E- ~
  130.                         break;* j# X8 l& m- j: R  O
  131.                     }
    # G: q& |8 L$ ^6 ?
  132.                 }//while end
    / o' G) S! [8 h4 k; \- b9 }8 z/ e
  133.             }
    7 B  Y& J; c3 r  E+ W
  134.             catch (Exception ex)
    . W, c" @* _# t- A  \
  135.             {1 w$ s! Q2 M  d
  136.                 //整体异常处理
    ( a3 v* {. M2 n, j0 q5 S6 u
  137.                 if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
      N5 v) w0 t0 t- j1 f4 s
  138.             }8 ?6 h' i" H, \; ~+ I
  139.         }! n" _& e! }4 `/ j% i

  140. ; y/ i1 ]! L1 x* w1 N- T
  141. / u1 }7 J" W) P' J1 {' a* S
  142.         public bool IsReusable
    8 f& ]. Y1 \$ y; Q) D6 f0 X# z
  143.         {2 ~5 j* L$ i) l& t0 U" g$ h
  144.             get
    3 ]. W$ Y, A2 ~% {3 J+ A
  145.             {
    8 C& B( o, P' [4 s. G1 o
  146.                 return false;
    9 M$ G' W. \" P( u, j+ G; l
  147.             }; h: B3 \( J+ l# S0 `* Q/ r$ p
  148.         }
    ( J& Y' z, C: `8 i; q
  149.     }$ x" X; i3 q1 \* l
  150. }
复制代码
4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径

6 c1 _! i' e0 W6 x5 Z* }
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-12-22 12:01 , Processed in 0.131619 second(s), 23 queries .

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