cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
$ K8 |5 j2 R- b2 X1 u" E2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;
) ?& O0 s0 ]0 l8 n6 t5 p, t - using System.Collections.Generic;
0 Z8 K) w8 Y6 I- `/ D( _ - using System.Linq;" C) K o ]! Q! o/ F
- using System.Net.WebSockets;
: `4 z. U" N* f+ U - using System.Text;
4 y: P; |+ ^5 K9 F/ G+ k2 X Q - using System.Threading;
# ^) {' |# @- m+ U8 c# P - using System.Threading.Tasks;! Q: m! p$ p5 g# a5 m7 x
- using System.Web;
) m0 Q) u1 K' ?& V - using System.Web.WebSockets;
2 J0 M+ z' O- U
+ B& N; H8 d2 a$ z; T: V5 K- 5 x9 w& s6 c+ y& o4 C
- namespace WebApplicationWebsocketHandler
& O1 n H+ G" G6 B* k$ | - {
. r& I. A. [# x - /// <summary>
' y% G( a/ U0 o' c1 x. z& R - /// 离线消息3 I) p8 C- T) z/ v
- /// </summary>
# V% D4 W' q! E6 e" s& M - public class MessageInfo
8 ?3 \* n5 k( z2 t' t. v - {, w! K$ ~, ?+ }) K
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)6 E0 |; s# `3 W0 U- ]/ q: s8 B
- {. S' d, F) r0 b8 k8 z9 O3 w7 K
- MsgTime = _MsgTime;* Q. f6 ~4 v. X4 B
- MsgContent = _MsgContent;2 U& s M; M$ {% {; P/ T" |% s
- }- i9 {; l; J; E4 ^
- public DateTime MsgTime { get; set; }
9 X6 \# ]( E) F: W+ \ - public ArraySegment<byte> MsgContent { get; set; }* b7 f/ K" V3 v0 c2 N
- }
5 u" F2 i. D4 i3 e3 @5 B
1 e8 t; z- H; s( E
$ m2 _( d4 p$ Y1 m T0 N& Q' ]7 ^ J/ q
; N# r6 t% a- i1 e U) _! _- 0 V8 i* ?3 e- H2 y7 V* A2 A
- /// <summary>$ B Q5 n! E9 ]
- /// Handler1 的摘要说明
# ~( {4 B. G7 i0 x - /// </summary>) C# J% ~9 n$ h5 D# w& W/ t' c
- public class Handler1 : IHttpHandler
" q* L) x) D+ ]( {0 ] - {
( F v- f: j0 F2 b/ [3 k - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
9 H- B/ i U6 g r* ^ - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
9 {& Z$ H; L( b0 {9 T+ t z - public void ProcessRequest(HttpContext context)
) d' l1 ~# x) H! b8 D& N5 O) P - {+ C. [8 `. v/ M4 p- q
- //context.Response.ContentType = "text/plain";
, t- Z U2 F' z' C; L1 z$ v2 v - //context.Response.Write("Hello World");0 u& Q9 s' W9 k- [3 p
- if (context.IsWebSocketRequest)
0 a* R; X7 {2 `4 m7 L4 K# { - {7 {: a. V8 z: {& }" F( Y
- context.AcceptWebSocketRequest(ProcessChat);
: h2 o1 A& f3 j - } 2 `. z1 r& Y2 H9 G" c+ K
- }4 F+ w; e% t( ~
6 p" V2 T# B# p' o" c- private async Task ProcessChat(AspNetWebSocketContext context)
5 q$ l0 Y( ^# c+ c+ X4 z2 p6 y1 k6 Q - {
& u2 _% Q7 j# U# ` - WebSocket socket = context.WebSocket;& P& Q* D! ~$ N/ J" i
- string user = context.QueryString["user"].ToString();3 _# w0 m& b$ S
# F/ C, j2 R% G- try. { Q' x; N- e8 d2 z/ E
- {& ~$ k' Q- i* L& b+ P$ }
- #region 用户添加连接池$ b, x# M- B4 s
- //第一次open时,添加到连接池中, t- r6 }( y+ l: \: p4 {; w
- if (!CONNECT_POOL.ContainsKey(user))8 ^$ _8 A! g6 D6 p+ A
- CONNECT_POOL.Add(user, socket);//不存在,添加1 k8 ?( f B$ O! C; ^4 P( o2 j! C
- else4 a* Y8 T" y4 S, U3 y! a- U1 p
- if (socket != CONNECT_POOL[user])//当前对象不一致,更新, ]/ R+ T$ j8 [ o7 ^
- CONNECT_POOL[user] = socket;
/ E z+ X' Y6 I+ u7 m8 ]# ] - #endregion
z" A- i, ?1 j% O2 V# d. ?% u - % o# D% C- l7 ^/ C$ A$ u& s& e
- #region 离线消息处理4 ^- v+ @5 E& Z) i2 m
- if (MESSAGE_POOL.ContainsKey(user))
* k' I# ~2 F& r3 E+ ]& d* K - {
5 P7 B! w( C2 ~ - List<MessageInfo> msgs = MESSAGE_POOL[user];7 i; G( z4 ^# {, y
- foreach (MessageInfo item in msgs)
# V% Z, A$ `4 \ - {; ]$ {& H3 X/ C! s
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);9 K+ n" g" w; r u* H- G# s4 Y
- }
|4 `# M& R$ {+ P - MESSAGE_POOL.Remove(user);//移除离线消息
2 w, E# t0 R1 N& k; g: J3 { - }: f$ P! D8 x& g* l7 R
- #endregion
- N( ~' y5 `4 k; v - ' A: F0 h% _: M
- string descUser = string.Empty;//目的用户" a. {+ `/ F7 H* o
- while (true)
" {' X+ S+ T9 a. V+ Y) {: F; ~ - {' q: }3 t& q( u
- if (socket.State == WebSocketState.Open)
4 t7 O. p; C9 R( A$ M - {
! R% Y6 u$ g. P0 N8 R( h - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
( y) i8 i! c+ t0 i2 Q7 Q$ R" \( Z4 V - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);% M6 u2 G; W T- g( U
, k1 [3 h3 O6 T1 v6 ], L- #region 消息处理(字符截取、消息转发)3 v9 d; w" x' K g1 f ]+ n' v; D/ [3 m
- try
5 j3 q0 @1 z) S5 ]& B - {! v& K% O& R* n- q/ v0 G: [
- #region 关闭Socket处理,删除连接池: K" d9 b' d* o) U
- if (socket.State != WebSocketState.Open)//连接关闭6 ^" k9 j j) E9 ]/ Z
- {: c6 E& F. P6 x* @% M
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
' v6 q, T0 E( T" T - break;
+ f7 d+ k! A/ r - }
& t" t! m$ Z3 |* Q' [. U0 u - #endregion! ?" \& A) N4 X6 b: x
- 1 P( S+ ^4 Z8 n5 |4 i* r. Q2 ?: Q9 U
- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
7 ?! T# P3 u, E- l* Z - string[] msgList = userMsg.Split('|');
% o( R3 }* [# g0 g, ^0 Z/ A - if (msgList.Length == 2)
( q$ d9 O% n0 b, Z" H+ d - {# G2 c4 H. ~* l3 c& [
- if (msgList[0].Trim().Length > 0)* C0 m6 L* V+ c% A! j5 L
- descUser = msgList[0].Trim();//记录消息目的用户% @1 f% C4 B. W: B3 [- j1 B. P4 V
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
- J6 }! |+ B0 m! `3 L/ W% {, z% A - }9 y$ P& D! _9 m$ Q5 `9 I3 {1 R8 ~
- else
$ S2 G( R1 G2 r# x - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));0 h B9 s' m1 d3 H- v
- ' {* J/ z8 v6 b0 r" U: s
- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线* [8 @# U9 R/ R# G$ n
- {8 s( W2 S; A8 T, I
- WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
' W1 z: J4 `! k: c+ j( z - if (destSocket != null && destSocket.State == WebSocketState.Open)& I$ U$ X! g$ j% V" q+ R
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
' T) S6 [0 N: x) \9 N; \ - }& c1 q3 @. h k: r
- else3 X. O" g- J' p. Z
- {7 ~- }3 s8 i0 O/ `( d1 g$ Z
- Task.Run(() =>* p1 j3 {, u8 g6 i0 C
- {) H( U( v* q5 t6 f% F+ y
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
; G, S2 a& k1 e$ V1 U - MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
x/ u9 c; {) H7 R - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
3 C! u5 A6 a4 \ o& L4 p - });
3 M& K; W2 O7 e6 k - }
7 {$ M! \7 n+ N9 ?# } - }0 b3 P- I& |: Q& L6 y/ S
- catch (Exception exs)# d# Q+ H* O+ M' a
- {' |1 s# Y: |) a8 M
- //消息转发异常处理,本次消息忽略 继续监听接下来的消息) t6 o3 u4 T( z! G# P
- }# {; P% j" e$ Q
- #endregion8 n; n0 B' G; p: ^+ z; ^
- }
( n8 R0 r7 m# i6 V6 K - else
- z `. f% k, s/ N1 } - {: L R7 T* B3 `3 |6 C
- break;
! {3 ^2 m; x) q: m* V9 Y1 l - } f' {6 z2 \! b
- }//while end
% A6 Z( v' _7 @: a - }) K" m, Z# p4 v) G
- catch (Exception ex)
' x* t V$ Y Q1 O. [7 M- F. M5 r - {
. H' A# G" ]6 X# V `- U5 | - //整体异常处理, B# ]5 l+ _+ l$ W
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
4 Q, V- _! f+ i/ } D( z% {+ d; d - }4 N1 W- z" B! p" f, v# y
- }
R. C3 l2 v) \# A ]
9 K8 g0 M% \% E. \2 M" M( g
, ~1 u( A: o. l" X* n- public bool IsReusable0 L, H$ N! x: p: B# a& S
- {/ r/ ?. J% ^6 n" t
- get$ K# z5 z' F( ^9 k/ G# f1 g+ u$ p9 C; a
- {
+ B% [! T6 n3 k& T, g - return false;
- C C) Q: K) n$ f - }8 k$ X+ N, Q( {. }: k* L. [! o
- }
1 ?$ w( N4 h) H5 V5 z# _ - }# I+ L1 R; a5 D7 g7 f
- }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
. ^0 Y4 S/ k& f. ?
| 欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |