cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
, ?# W$ P5 q+ O O$ v2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;0 P; A; V, U- C% ]9 {
- using System.Collections.Generic;
G" L/ m. s6 W - using System.Linq;$ z, X- _8 F Y# q6 v, d: T1 t+ P
- using System.Net.WebSockets;
9 ~6 J+ W' x5 i - using System.Text; k; _6 o$ A5 B6 w
- using System.Threading;
' ]6 d% q3 P9 p3 C - using System.Threading.Tasks;
; q# Z G8 i7 ` - using System.Web;: r4 U. }- k$ f6 `" W* h J
- using System.Web.WebSockets;
; l" B8 r5 K4 x6 x/ k
, l* r% B' p' p1 I
6 @, r. D! t5 s3 _7 @! D2 W$ s- namespace WebApplicationWebsocketHandler) W) Y3 T$ o5 O; E* j
- {
3 t3 y/ o \3 v: }4 p6 {, w+ \ - /// <summary>
3 l3 S7 t9 ^; L# ]+ Z" `! D - /// 离线消息
2 o1 Q; V! K3 _ - /// </summary>
+ g- z9 c( W& C3 q1 s3 q - public class MessageInfo
: l7 h- y4 f! j) S% \ - {/ n7 {, `7 u4 S1 s4 E# }1 g+ c. W
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
/ B# Z; i& V/ m: V - {9 A4 y* P) r4 T
- MsgTime = _MsgTime;' F# _8 S4 \# h$ V3 |& }4 B& J. e
- MsgContent = _MsgContent;
7 L- x/ x" Y2 r/ f% `( ] b - }! W3 W$ D f" B* o
- public DateTime MsgTime { get; set; }
+ f" `6 w, e5 p/ D; Q! m - public ArraySegment<byte> MsgContent { get; set; }
8 K1 Q( `$ X' ]+ h1 N - }: m1 Z% S% d6 e) @# R
- 3 y/ j2 H0 Z% M& `+ j+ I w
5 H- m" E7 A( t6 R& |) N- , H) E6 B; U8 j/ S7 f4 t2 w
- , E+ l9 K( Y3 B, Y, c8 |
- /// <summary>
+ I& B) H* X9 g! D* G) q" K* h - /// Handler1 的摘要说明9 r9 B# o; F& O8 @
- /// </summary>4 Q; F/ l4 ?$ _" G. F3 R7 ]& ~
- public class Handler1 : IHttpHandler
; a+ }# [, t! E9 b# Z - {
8 K5 ^7 ~1 `1 `$ K - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
5 Y1 H0 {* o( \: x - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池1 o* d* c1 R" O/ ?" ?9 f( ?
- public void ProcessRequest(HttpContext context)0 |& j* N+ w# m8 |) b6 X0 `4 z
- {2 T( x: ]$ A! ?( }/ q4 `& \5 B
- //context.Response.ContentType = "text/plain";8 n0 A- ^8 Y* b0 o3 n0 n
- //context.Response.Write("Hello World");: q) t; C/ p2 g, `) s) m5 a
- if (context.IsWebSocketRequest)
0 u6 A# C- }# @( e0 [ - {
) z, K5 S+ j, q. A - context.AcceptWebSocketRequest(ProcessChat);
# U1 ]/ X% b' ]1 G - }
4 D. k5 m H/ x! h; w; D - }
8 k$ ]# M4 r2 z* a
7 \, k' ~* z+ z) c2 F8 h& g- private async Task ProcessChat(AspNetWebSocketContext context)9 n" n& V6 ?% P6 M" {7 N
- {( D: A5 ^% F ]0 \1 ?# h
- WebSocket socket = context.WebSocket;
5 n5 A5 m8 z0 Q# r* b+ C4 n. V - string user = context.QueryString["user"].ToString();
5 X) ?! z S: i4 o - 2 z2 G' N% r8 u3 {
- try
3 @2 G1 ?% Y, L - {( f2 ^$ ]/ h% i$ p; v
- #region 用户添加连接池; x/ c! \6 g1 d* t' I# S/ d
- //第一次open时,添加到连接池中
3 O j& `$ p& C2 x7 @9 H - if (!CONNECT_POOL.ContainsKey(user))
! `4 q! _) j7 J. v2 w9 W$ j, P - CONNECT_POOL.Add(user, socket);//不存在,添加$ V- L! h9 G6 a" ?
- else
7 d: k3 H8 h! O- s x - if (socket != CONNECT_POOL[user])//当前对象不一致,更新
) f, B8 g( F2 N - CONNECT_POOL[user] = socket;' p2 G- G% f2 K f/ C
- #endregion$ R% L: w) T6 T d( b# D$ D
7 s& ?- t3 s$ Y- ~. s- #region 离线消息处理* T5 E1 R& k/ @4 N
- if (MESSAGE_POOL.ContainsKey(user)): J6 M- r6 \' |* X
- {$ A, Y! r- v) Z$ V
- List<MessageInfo> msgs = MESSAGE_POOL[user];
# \/ P# _/ e1 P' K2 `7 Z# V - foreach (MessageInfo item in msgs)) R6 M2 U% x3 f) E5 }) o6 i0 k3 C% q5 l
- {: y! N) V/ a% s" x( G$ ]
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
1 S- b* X; j: J/ ` Q' i1 o% f - }
5 n I$ ~+ P2 L1 Q! I( R - MESSAGE_POOL.Remove(user);//移除离线消息2 n3 W/ T/ d! G( a% p
- }3 [, g0 j9 f; M: u
- #endregion
9 L6 d! i1 ]2 q0 W. B! j
, ~. i8 f5 r) \1 r& ~2 N- string descUser = string.Empty;//目的用户
1 ]" W6 }2 d7 _, y" k0 W - while (true)$ y9 V5 `' ]0 h* c
- {
* X3 s: k2 L2 h } - if (socket.State == WebSocketState.Open)
, i0 [) R7 H- [! F) J6 ? - { q7 f4 T2 o0 M
- ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
' t2 p, S4 v6 u5 n* e7 \3 l: p6 D - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);$ O; z9 ?* V$ `% f0 T
- 8 z# }6 x, ^" N+ F! D! [- N
- #region 消息处理(字符截取、消息转发)+ p7 Y- Z1 P! f/ a" R7 x
- try$ t8 h- Q7 _$ X& {# P4 a- ^% @
- {
s! o: E' W% s - #region 关闭Socket处理,删除连接池; }9 @9 v9 C# V# d' @% B$ c
- if (socket.State != WebSocketState.Open)//连接关闭
( F A9 i `$ C2 X4 b$ W - {
+ `; c! ^& F- o1 G$ }" N* R" } - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池0 ^+ D& y( W* r2 F
- break;1 {2 u2 `' T( Y. [, v
- }: y9 F' c& ~* K; Q7 O2 G5 C
- #endregion
# O# z+ y5 D% |# I" t6 t - 6 @9 `( `$ ?+ L
- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
! H6 ~# Q- _0 \1 ~4 H - string[] msgList = userMsg.Split('|');
T) u( M/ K" X) Y. Q* ]( t - if (msgList.Length == 2)
8 ~6 L8 K0 E; L& S# y - {
" W; E2 [4 u2 R5 c1 e! h/ v - if (msgList[0].Trim().Length > 0)' s& }1 Q) d* F) J- ]. j& ~
- descUser = msgList[0].Trim();//记录消息目的用户
: a# f! S$ [$ I( H( E W2 P - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));9 ] ~* Z$ }/ x0 M' K
- }. L( I B) w) i0 O3 T3 ~; [ F/ o
- else
, ~ G: p1 d! E" l+ Q. G5 O! E - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
" ~. d7 ~. m4 O- I) g - * @3 }7 @: _ ]3 B9 L
- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线9 }0 x: U1 y! C% _3 s
- {* Y( |" `( U* h; |
- WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端8 O% X( |& R- N2 x: S8 v
- if (destSocket != null && destSocket.State == WebSocketState.Open)
0 k9 t0 t2 }/ m+ c2 _; o% t# j0 ` - await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
/ Q" c& @6 y: j3 C - }* q3 d- F, i! t1 j8 K& u
- else; o. E9 E Y T6 h% r+ L
- {
- X8 r' V! B m& k3 a2 Q! n2 a, \ - Task.Run(() =>2 K7 Y8 F* I _1 t4 j
- {% {* K& F. }$ B: V( F
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
- i. |3 m' z- [- b6 q' q U9 S9 {( I& m6 ^ - MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
; {2 T& e+ l8 k$ p2 U1 H0 L - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息* ?5 J( E' g3 \% B9 ^/ F% s0 u" c
- });, T& Q& x* g5 Y! n+ ]" ], O
- }
/ k1 g4 ?% V# B8 \$ q - }& _+ b* K1 T5 ]4 {3 z' {0 B
- catch (Exception exs)- U8 P- Z9 q7 x) a1 M/ x
- {
4 a' ]. h# ~; X. v - //消息转发异常处理,本次消息忽略 继续监听接下来的消息! ?* e5 J4 _5 |4 A, c
- }
r" g3 W0 Y$ O. l2 ?$ q - #endregion
5 f; } j% u, U. R - }, z0 I$ R9 @! @; I! s; I0 Z
- else
6 S u+ ~; Y! Y1 d; ~" Y - {- S6 c0 ^4 I5 ]4 t
- break;
+ I) i1 \- ~* q - }
. `$ V b, I8 l$ C4 w - }//while end
( D+ L: |" [: ^8 [8 ] - }1 `3 _: E2 c. {
- catch (Exception ex)5 i0 O* K3 {# z m! e" y; g' {
- {+ ?' I! b4 F. \- i1 ~9 M/ v, Q0 R
- //整体异常处理
( D! g% j9 E/ A: h - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
9 ?& `* g) a h/ I( o9 W - }
+ G; Q0 N4 _0 F - }, u7 w) @0 z* R- `& f' [& g
5 j( ?+ m0 I: ?' f, M- & e* l" s, p4 {
- public bool IsReusable1 s8 z! A" Z7 g E
- {
- p' Y- r: ]% `% W. b - get
7 \2 k, t+ g! o; _$ [1 H - {; u/ V# \6 ^ T- m) E
- return false; m& [/ n; N1 q8 O; _8 z& l
- }
/ y* Z: ^ M9 a% M4 ]6 b$ ]; i3 f9 y, X - }) P: u$ u9 |1 k8 k
- }: Y. v5 q0 K, \3 \+ i9 S- p. j
- }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
, Z( ^ W e& b& f9 u' C
欢迎光临 cncml手绘网 (http://cncml.com/) |
Powered by Discuz! X3.2 |