cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
8 k7 Q! E4 Y' R; x5 r k& e2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;
f* p8 t" v3 N% \1 L5 g - using System.Collections.Generic; d1 @: y& E0 Q) H- \; m
- using System.Linq;' e O; M& k' E4 Z3 A& a& E' X% O
- using System.Net.WebSockets;
}* u4 G" ]# H. T& u, J - using System.Text;
& M- k9 b6 b% u* J A! |" M - using System.Threading;
1 U$ c6 {: f; T# x" V - using System.Threading.Tasks;: l+ x! v- j1 Y4 z
- using System.Web;
# \( H8 p. |8 Z - using System.Web.WebSockets;
+ T) ~, h0 ^0 t; u0 l - - o w3 W$ M; l* S# @
- & v7 I" v& W% E
- namespace WebApplicationWebsocketHandler( c4 s( A( y# B7 V
- {% N9 r4 f) f& f7 \7 v7 \9 B D
- /// <summary>
! U( {+ u i0 S$ s - /// 离线消息
$ b5 o, l- {8 o - /// </summary>
$ j1 l/ h2 ]0 E2 O( O4 [+ a7 O - public class MessageInfo
6 g, K: _ X; _; l6 x - {$ v) m6 @5 m& o$ h& y
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent) ]* X, p# ]& N
- { S" l" P0 O- d0 Z0 G1 ` z- m
- MsgTime = _MsgTime;
7 H4 l7 K* q+ O8 c+ z& {4 n L - MsgContent = _MsgContent;
1 c. j0 v( `/ y) ]0 { - }$ _! Q6 M2 I: o! y. o9 w, w$ D" Q
- public DateTime MsgTime { get; set; }
5 R+ Y6 n5 `! S* D$ |# l" l% M - public ArraySegment<byte> MsgContent { get; set; }
& e# A& b: X# q8 I+ m! R' L1 v- m - }, l% x+ _1 Z% s" q( s' s8 b# k" P) D
- " d( f) r; ~2 i. q" K
- 8 A% p5 E% }% M/ T2 O7 ^
- 7 h u; v1 F: T, E
- , R u1 i/ D' {0 R# u6 s0 w
- /// <summary>
7 T3 n1 y* u9 i6 A& f, y8 d( l - /// Handler1 的摘要说明
& h, X5 v$ n; V7 P( g' u* z - /// </summary> c J" j. k3 Z/ j# Y5 S
- public class Handler1 : IHttpHandler3 \4 R/ T) J }! h
- {
- F( }4 I' V$ ^4 v$ w2 a2 J( N - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
* {: K9 E9 u; i, N$ F5 P0 G# F( J - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
5 L c0 ^% |) L# S - public void ProcessRequest(HttpContext context)
4 V8 a/ D* `- \% H - {! L2 y' E' k. g4 K& Y
- //context.Response.ContentType = "text/plain";6 R9 ^0 w% [4 U6 C% ^8 b; Y
- //context.Response.Write("Hello World");
8 ?+ P; e8 @7 ~% J& { - if (context.IsWebSocketRequest)
# T$ O" o$ b5 \* }, V - {
, E6 g7 Q# _+ i2 _1 U* l* E) S% a - context.AcceptWebSocketRequest(ProcessChat);) n4 p0 @" t7 @+ q
- }
' D+ L# t3 |- `3 R) V* H' w - }
, I/ A# d$ `# ]
- t; q* \3 l: l* C. `1 d$ G- private async Task ProcessChat(AspNetWebSocketContext context)
7 ~1 y7 r- ]2 T7 u4 S: I - {
2 _) j2 h: k) B: ]4 [6 k - WebSocket socket = context.WebSocket;+ B, h8 K+ v2 C
- string user = context.QueryString["user"].ToString();
1 E+ g6 Y6 W2 U( v& n - I J5 y9 k5 ~. Q
- try& N) u# [3 Q, [3 W
- {- B& f6 i! q ]$ |- {% L
- #region 用户添加连接池" E! b: a7 {" P" r4 x/ z# |9 j8 ]
- //第一次open时,添加到连接池中( U" v5 h1 }4 r
- if (!CONNECT_POOL.ContainsKey(user)) V+ E2 D0 K" i6 Z
- CONNECT_POOL.Add(user, socket);//不存在,添加5 a$ n! m6 E$ Y4 ~
- else
7 K) z# E7 u [2 X# q0 s - if (socket != CONNECT_POOL[user])//当前对象不一致,更新
2 }0 Z7 f% B q) n* F$ C - CONNECT_POOL[user] = socket;
8 e% f$ F& t5 b* E3 t - #endregion: f" e, ?7 O" s" a* j
. J* l; v" y+ N" H6 s- #region 离线消息处理
9 r: o8 E N4 s# j7 ? - if (MESSAGE_POOL.ContainsKey(user))
, e( ?: w- p V% e8 q - {
5 v, A3 X' y: e* G - List<MessageInfo> msgs = MESSAGE_POOL[user];; ], j! D1 T$ {. V
- foreach (MessageInfo item in msgs)
7 h1 y& {9 y, F5 L- S3 u o) U - {& [: U- W% J! J3 {! M
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);$ {& _6 P. `: V7 [# Q
- }
( B# y5 u% E; B$ s" W3 k0 d4 r - MESSAGE_POOL.Remove(user);//移除离线消息
9 L8 `! h, O+ s5 h, T) m$ i - }1 a+ I$ e4 M& N! b3 i9 j
- #endregion& b) q! A# m! n+ R6 U% c
- 7 `6 W6 z# q; I" q
- string descUser = string.Empty;//目的用户
, d( d* C2 R$ L9 ^' M6 d j - while (true)
$ d3 A# L. C$ A* |0 J1 X; Z - {' y) _+ H L) Z8 Q- O6 D
- if (socket.State == WebSocketState.Open); U, q6 J3 x" s
- {2 t& Q' w2 I5 M4 j W8 I( E
- ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
# G r9 A% ]$ `; h' s) L - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);" k; A( c: L7 t2 p1 `1 y; C
& U- b- Q2 Z. r& Y# P- k- #region 消息处理(字符截取、消息转发)
, H% O. E3 A2 ^! \ - try
+ K* r" m3 H; `( c$ A; t - {
. O2 ~# t# t$ w. g1 c8 V7 A, Y) a/ d - #region 关闭Socket处理,删除连接池
' @+ I& @ W7 W2 Q5 f. [- q& x - if (socket.State != WebSocketState.Open)//连接关闭
2 g6 l+ D3 o/ n6 `* ~6 W* Z6 E - {
' y' x7 G+ m1 D; U3 \ - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池5 G6 B# X$ p/ w9 V q* J7 P! F1 i: ^
- break;. x2 z7 T, i$ N/ V7 M4 S
- }5 ~7 z, Q2 F' A6 }+ {) o" R
- #endregion* b8 F/ g1 b: M) V
- % Z$ ~& A; H* ~
- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息4 L" T6 }! H3 ~$ A; [" p' I
- string[] msgList = userMsg.Split('|');
3 o( T Z* C( [+ y3 H/ T6 ^# p& y - if (msgList.Length == 2)1 O4 N: l8 M! [7 p' |2 F
- {. u8 L* D- B T
- if (msgList[0].Trim().Length > 0)
# n- T4 s% v, f - descUser = msgList[0].Trim();//记录消息目的用户% f) n( C- E0 ^ y
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
0 Z) r( B# p4 l, G2 P, F - }
t9 e$ P0 r8 A# U: ^/ W9 ` - else/ Z3 B& F3 S! Z
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
4 H- k1 ` D! w- V4 O) m8 [ - * K1 G" b6 Z% {; g% @' u
- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
( S2 p& D: V/ c6 x6 Z - {$ w' C+ T _( @; q, u. ]/ Y' p
- WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端) K, [- }3 m% } }
- if (destSocket != null && destSocket.State == WebSocketState.Open)$ Z2 C1 B( u/ F$ o6 I% x% C
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);4 A. O/ j) R- @4 V" k
- }
2 j/ m: r: T" u3 N$ R H. k0 e - else3 A) [! ?9 \' f
- {
7 s* p6 \3 O8 y g. m0 G - Task.Run(() =>
& z- y4 \, x4 t5 u4 N8 j: g: @# T - {' ^( ?7 c0 R7 R- u6 r9 H4 @
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
Z; U, _ m- j - MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
5 @* I% O) \: A K - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息, ]! f$ ` ]$ u, D, P
- });
5 ~; m: w q/ }" M8 j) C - }6 \4 s9 b9 I0 o0 p9 S! z
- }
2 b% O* x; l% w ^: M/ M$ Z/ C - catch (Exception exs)
8 H8 V' \' T' A - { S. E _- p1 |& T/ h$ \5 @, [
- //消息转发异常处理,本次消息忽略 继续监听接下来的消息$ N1 b. Z3 Q% M* ?
- }2 X; y9 |9 P+ w) Y/ l
- #endregion
9 X l$ }3 C* S, N) }2 ~: N4 O - }- B( _9 `. w# ~( I) k& d
- else" O* l$ ~% o, N% c+ O
- {# j! S3 g3 }( v9 }, S
- break;) k. R' f9 u; B* u# P. O
- }. f; ^6 @1 p0 O3 j$ p6 _
- }//while end# Z" m, U8 g; s; }$ F! s5 J& f
- }
8 _' H' @, q% z' L5 K2 a0 I8 ^ - catch (Exception ex)
. h; v# K2 ]7 Q8 K# k8 _) E - {
& U' n% y$ L3 p* p4 v2 T( D+ i - //整体异常处理
# G. [/ K; i# S0 w* J0 {4 a7 @ - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
) T9 f% R) K: V+ o - }
" e; w4 R% f, m - }
. r4 }$ Y0 q$ y# ^0 [: m0 w
% u( O2 V# @ d1 c
+ G0 r, I$ }/ b2 K. F4 e( _. u- public bool IsReusable
* `/ s: G. p U& b1 z - {
9 ~" U; F9 `. N+ `! S) z - get$ f# n5 H0 M: g/ B
- {& K; m1 O( q/ \+ h5 c, }% A `( s
- return false;
+ ~+ Q5 A$ ?: D4 _$ _# b - }
6 J. Q; u' `, } j - }
8 K5 t4 }6 g( W, j; T - }
- w0 T R8 f+ k7 R( r% Z2 q - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
5 O2 I& m, u# O
欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |