cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
& m% ]: N8 t/ [2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;5 A+ M! K0 R9 B
- using System.Collections.Generic;
+ G6 n8 ^8 h9 u* [* z0 J - using System.Linq;5 l, \) a/ P1 w; j
- using System.Net.WebSockets;
/ J5 P3 u9 r* ~- c' z" C - using System.Text;
/ C$ @6 E& ]6 ?: X - using System.Threading;
3 k/ n( |+ D2 s/ R+ M0 i, z - using System.Threading.Tasks;
* T0 l( C+ g: [7 j& B, z9 D+ X - using System.Web;
4 _/ A5 w" Q7 O. i; R, L+ H - using System.Web.WebSockets;) K6 B/ M' ]( P/ j) ]' v9 T `$ r2 U
* V' L9 I: {1 U" P+ R$ o7 u- 5 i$ ?4 i) \( C1 b
- namespace WebApplicationWebsocketHandler
9 N8 y4 m& ~( ?1 a - {* x U* `! V! Q+ T) Y0 U
- /// <summary>
' V2 B. C2 i; v, Z* Y - /// 离线消息# X4 A0 l6 c1 d5 ?4 n, f% R
- /// </summary>
3 ?9 ]" h% C+ f" R- d' C. F! l - public class MessageInfo0 J- G5 |, b( z# ?9 t4 _8 x
- {4 [' b4 f1 e* Z% ~
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
+ g7 o! c/ Y! j - {
( N" F& j% x. c6 h( l& `/ }. g - MsgTime = _MsgTime;9 g9 t( j8 F. ?8 [0 b; @ T
- MsgContent = _MsgContent;
8 W+ l8 d0 d0 G - }, c$ D& k7 t3 u% Q$ e4 |, C5 G0 d
- public DateTime MsgTime { get; set; }
7 H9 s b+ ^. a! ^+ E - public ArraySegment<byte> MsgContent { get; set; }$ R: t% n: l* w- V5 @
- }
* t3 J; x) n& F6 m$ G
( Z* [5 q4 _- l! D- 0 x! c Z1 ?: ~; D& @7 |3 f! q) Y
- 9 g) w# W. {! k& ^
9 J8 Y2 e) [: A- /// <summary>
- G& x' o( t' W; t8 ]* ?4 O, }8 r - /// Handler1 的摘要说明
- b* m" i7 c" h2 i8 w - /// </summary>0 |1 w% b# I8 q0 U8 p) k; u
- public class Handler1 : IHttpHandler$ A! b- P; P9 V7 G
- {
+ x/ E4 l) w" ] - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池0 J4 |: k; B; a' k
- private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池& d1 b [) m7 W& Q
- public void ProcessRequest(HttpContext context)
3 l$ ?( `1 }6 W" D - {
9 J; `5 w8 d' p9 X - //context.Response.ContentType = "text/plain";
! {0 ?, C& ?4 E/ Y1 u0 ]. n1 h - //context.Response.Write("Hello World");
0 V$ W* Y1 k0 |+ e9 E - if (context.IsWebSocketRequest): r% f0 R: h) ~6 b+ {- `
- {
& [9 O6 S! ^. Y - context.AcceptWebSocketRequest(ProcessChat);
, L% ~ @; L a3 N. y! \ - } : j+ V/ t4 v P9 E9 \4 ]3 u: Z
- }
. n1 I; T/ }5 C9 p0 N! L- v6 G - ) H: a/ w/ k- L; v" ^, A
- private async Task ProcessChat(AspNetWebSocketContext context)& D* ]7 p9 p) r" q
- {8 Z3 T5 P1 T' @& R, z7 Z
- WebSocket socket = context.WebSocket;3 z; `2 Q- A) N- W+ o
- string user = context.QueryString["user"].ToString();4 {7 K7 {! N \- }9 i
- + S! _# ]: L2 G! u4 y6 }0 `
- try& ?* [% [" x/ ?1 _
- { N3 g! [6 i @
- #region 用户添加连接池% \; V( n6 h0 R1 ^. ]" M- N1 T
- //第一次open时,添加到连接池中# k- D$ b% B- b8 A% x
- if (!CONNECT_POOL.ContainsKey(user))+ f/ ~+ a* _% U c* S
- CONNECT_POOL.Add(user, socket);//不存在,添加& g, e% Y+ n" V% C$ A8 d! P$ s
- else
7 h( g0 Q2 B8 r( f: [ - if (socket != CONNECT_POOL[user])//当前对象不一致,更新9 \- K( U( ]. a& l! q5 Q- K3 j
- CONNECT_POOL[user] = socket;
9 M8 Y( @' ~0 [2 x: N - #endregion
5 k4 R4 ]+ v. R8 J! U1 { - / n1 f- b7 K6 O0 M
- #region 离线消息处理4 z! r ~8 `. P$ {4 M
- if (MESSAGE_POOL.ContainsKey(user))
; M8 t6 m$ V. p$ u3 W4 Z. A - {/ q1 m3 r- \* S1 k: M* c- Z8 X
- List<MessageInfo> msgs = MESSAGE_POOL[user];
5 R, N3 p+ g& J+ o" A, ` - foreach (MessageInfo item in msgs)
8 F4 H) B& V0 u& k5 h" i7 [1 L, [ - {
7 u6 r! T! s i7 Y+ I4 _( l - await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
$ z; u& n ?' T7 a. @; ^7 { - }7 l1 S& X, n( z4 k. w
- MESSAGE_POOL.Remove(user);//移除离线消息
+ F8 f: R; E1 a - }
. s" q3 n$ S; _- N% X - #endregion
; C2 n% o) I/ F - 1 o; Y1 J& K! c
- string descUser = string.Empty;//目的用户$ q8 U h$ I; V% `, h6 W
- while (true)
1 U' e9 o! @3 }6 @# v7 p - {
7 O. c- B- b5 ^7 @ - if (socket.State == WebSocketState.Open)
- H0 p' L4 G2 j- D" Y9 ? - {
3 D: t3 U5 N6 e9 b) l, ~# q - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
! k& h( Q$ O( o! |7 m+ ?' l - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
9 ]* F0 J. p6 A( |* s) b - : E# O, P5 c" m$ I& j
- #region 消息处理(字符截取、消息转发)% v( F7 D1 x0 a! G5 Z: h9 F1 Z
- try
1 y0 v J; q4 o3 Z& w - {
% d( R6 ]4 a, v, u6 g - #region 关闭Socket处理,删除连接池. S% [' I" E- g
- if (socket.State != WebSocketState.Open)//连接关闭) ]% v/ }) o4 U! D
- {% v" ^5 U) ]' |3 P3 G4 |: |
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
5 j2 G4 y9 W) u Q0 m8 h - break;
5 K2 Z4 A9 {$ U2 K: C! \ - }9 V z# I% G7 O7 }2 y
- #endregion
* j2 Y! x/ _7 q/ O* C+ W" o% Y - " o5 W k* Z/ Y% s" M
- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息7 Z4 N# M3 S! n
- string[] msgList = userMsg.Split('|');
* T3 c$ U! G6 l - if (msgList.Length == 2); v* `0 V, O) z: j% A8 Z6 _
- {+ m- |$ {, v. j0 Y' u- I9 M H
- if (msgList[0].Trim().Length > 0)
9 \# g Z0 ]- H# j2 t+ O& ^ - descUser = msgList[0].Trim();//记录消息目的用户
% S$ Z/ n, O. D' g7 _- s: K# v - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));" o8 P/ j0 _, d4 B" c
- }7 u* i) O) R0 @( @1 k5 k! ?) [
- else
. Z# S! O* W) ] - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
# W! O% ^+ j. z. Z; _
) O2 n% c& L4 _! S* Q- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线& S' Q$ h+ A3 L% g, g/ b
- {
. P/ b9 V: P8 K - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
6 B1 u9 a6 S! h4 i2 P6 D6 s - if (destSocket != null && destSocket.State == WebSocketState.Open). e" |# i! e7 F' r* K; G2 L
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None); S4 a8 U: ]$ O: i4 Y- e) \
- }* A; A* f% N; b9 t- n6 t
- else* s/ s7 j( Q p+ N F
- {
, J/ F- y8 D& w8 q- B) L/ Y - Task.Run(() =>" W9 R4 A# r$ K8 k& N
- {
9 c- E5 s. D- n @% A - if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中5 k$ i) r8 P% S. R* L& n! Z
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
0 M6 @3 k, l+ n) G0 m! q0 B - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
( @* u5 r* F) R3 c+ x2 `6 L( Q+ p- l# y - });
! P, ^2 n9 V4 }/ z( S; t - }
' R1 x6 n0 U+ P$ J# Z - }
3 K, ^1 ?* u1 q7 q$ L) k/ F' Y - catch (Exception exs)3 d3 h9 K0 k1 j
- {
; l6 N. e+ i2 b' H - //消息转发异常处理,本次消息忽略 继续监听接下来的消息! g3 ?, g. @3 P' @2 R" e
- }
5 m: ~: _# {7 _% @: F - #endregion
2 A* y# B, A0 b7 u9 c# u# s8 i8 }) X - } F0 q1 `5 Q \
- else/ S- u; n# I0 O! ?3 A" u( P$ R
- {; \! \" P/ f: O: {3 B
- break;2 T7 Y Z: Y2 j$ N, i
- }' _' M K. A) K0 _% }: z2 ^
- }//while end
/ y' q1 F/ a( v. p8 W4 ], G& ]1 y: N - }: P3 Y) ^' I$ A3 ]; i% ?& R
- catch (Exception ex)
1 J) }* I" R( W" z - {
3 Q& y4 t' S, M& T8 m - //整体异常处理; O$ @" l& S1 q: o H) H
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
j" B$ ^+ z5 O* V1 Z# o - }
8 m; `, @; r; d. H, Q8 f - }' \ v; z7 {; v- v
- . E+ Y- E6 m* h/ s) ~- h- o
- - \0 ~5 T, r9 ?. S
- public bool IsReusable, Y! L9 `, J: W5 g$ B4 f4 Q
- {
& w- y& T$ |) G0 M" G - get
. u6 \* Z* k5 A" v$ O - {
8 y1 I; r. q8 V' `" r - return false;5 }& S5 g. p0 G3 w4 D) g2 s/ b
- }
. ]7 K# X! A& K S7 A: z1 x - }0 U9 ?: ^# j- p5 W% Z$ `
- }/ b& o/ \. B1 A) ?& s4 Z6 W
- }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
' I. W0 i$ b" i' N
| 欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |