cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
+ f0 ]4 F( F& C8 {3 l) ?6 N
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;
8 v1 o+ V: c. ?$ u) `, w - using System.Collections.Generic;% W% T6 g. I+ D8 N6 q( y
- using System.Linq;3 A& N! h6 L4 ~5 B2 r
- using System.Net.WebSockets;7 }; o/ } r9 ^% Q. w$ n% E
- using System.Text;
) r& T* J8 w8 Q - using System.Threading;
( U7 g! U0 `: h1 A s7 n - using System.Threading.Tasks;
' p. ~5 f& X+ F& K8 m - using System.Web;# ]( f2 ~ W$ z0 j0 T
- using System.Web.WebSockets;0 E% i5 T6 T5 P, y: u6 s
" {1 c# x/ ?' `" X- 3 t- w. Y5 g0 {% C" C7 ~
- namespace WebApplicationWebsocketHandler' ~+ R7 C7 J; \: h5 f5 Y2 e
- {
9 Z' H0 ~/ C/ w7 y; h; l - /// <summary>6 Y; ~' Z" g9 o* E$ f: r. ^
- /// 离线消息0 R4 o3 T, a+ g; S4 H( c4 X9 q% c
- /// </summary>
+ \) m! z8 Q/ l# ~ - public class MessageInfo e( A' v% q1 R- J# b: m
- {8 {" P# M' G4 B( F# a( ]: M# J0 s
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)$ I, a# v( C& |& `, w- O
- {: e! F/ _& i% {
- MsgTime = _MsgTime;
2 K" a2 e7 L0 F7 a - MsgContent = _MsgContent;
6 S% \. f7 r2 g+ \/ ] - }
/ n; X; Z' V5 J - public DateTime MsgTime { get; set; }
: {/ j. L/ g: E6 ~) F7 e4 ? - public ArraySegment<byte> MsgContent { get; set; }
. M: ]* K" B5 } W( w - }6 s2 ]( K+ `( k! |' `
( D& }4 G5 i8 }
1 F+ [& r; h, H9 {* I6 [9 i2 T- : r! l' y% C7 R
6 @* Q# D | j# t: l0 H( m- p' S- /// <summary>) E+ P. o( n% J$ p( n
- /// Handler1 的摘要说明. h! q0 U! U- ?7 Y+ a# \$ A
- /// </summary>, j2 R! t# X- a$ z4 K y- A; j
- public class Handler1 : IHttpHandler
; w& r1 ]$ V4 V9 g" y$ R9 q - {
% j! `' W0 h' I - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
: ]; N1 J2 H4 k) K( x - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
) j' O- T& N1 l9 F8 R V - public void ProcessRequest(HttpContext context)
d" \+ I' Q4 e! E$ z5 N2 h6 Q3 l- H - {
* I1 `& R8 S( c5 T& g- d6 _. P - //context.Response.ContentType = "text/plain";+ A0 A$ G6 l- n0 y
- //context.Response.Write("Hello World");3 z* o6 o. n! u7 F! X) Z8 W
- if (context.IsWebSocketRequest)' z8 K* h2 K/ t/ e5 v
- {/ }0 G7 S7 N. W) z8 G- h6 O) O
- context.AcceptWebSocketRequest(ProcessChat);3 M5 J0 ~4 ~4 t& \1 i- f
- }
5 c- c- y5 p4 s3 p, @ - }$ D% f/ s* n' p* n
# ~4 W1 i2 k7 _# `. F- private async Task ProcessChat(AspNetWebSocketContext context). f7 M8 ^+ B- |" f7 w
- {$ L% ~# Q# b: I7 C0 p0 l
- WebSocket socket = context.WebSocket;
. |: ~1 Z+ Y0 D8 ?- o7 J2 Z - string user = context.QueryString["user"].ToString();! [( A) r# \! u* |0 q& ^1 w
' B$ T s* [3 J0 A* D- try
) c5 n5 J1 v* g; U. Y - {
" I( n( k% p8 j - #region 用户添加连接池4 h/ k7 {. u6 ?/ m
- //第一次open时,添加到连接池中
6 a5 J) D; [! V. D1 ` - if (!CONNECT_POOL.ContainsKey(user))2 P0 {' D9 R0 W
- CONNECT_POOL.Add(user, socket);//不存在,添加
( l* ^% u: ?; |7 k - else
7 K3 {+ d# l- G+ Z1 E5 R - if (socket != CONNECT_POOL[user])//当前对象不一致,更新' o/ a6 n* |! w @
- CONNECT_POOL[user] = socket;
8 S# D+ U- x2 G% c0 u+ v - #endregion8 d- N/ e8 y# @# X
- ) V* Q$ s8 H( l' Q6 ^
- #region 离线消息处理. e1 G7 k( G x$ e4 h9 u) `
- if (MESSAGE_POOL.ContainsKey(user))) l; \ l+ O) d* N/ r) P/ k
- {8 p$ J2 a3 Y3 I7 y: _+ \$ D% E
- List<MessageInfo> msgs = MESSAGE_POOL[user];5 P7 s& E5 C: d
- foreach (MessageInfo item in msgs)
8 @, y9 s6 f8 U& v" t - {
" J, h: H: o7 Y! @8 n7 i - await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);/ h t6 A! s4 M( [% p/ L% I* |
- }/ ~3 Z& q) n! h1 u5 t) P
- MESSAGE_POOL.Remove(user);//移除离线消息
: l: I; e6 X7 N& o& x - }$ ], G5 V1 y# I) T5 u% k' d: I
- #endregion1 K H' N/ H9 k$ N! e+ k: K% W* W2 h
- 4 k K3 W2 i5 b* K" z
- string descUser = string.Empty;//目的用户
0 x3 W; o$ O% K a) ]1 t; C - while (true)& y. u# S( u g: W+ l O) X6 V
- {. U7 t" P' g( r7 {. ~8 p
- if (socket.State == WebSocketState.Open)
/ J$ Z) C6 g8 w - {9 ^; n+ H# { p
- ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
" H: t. K* |- a/ x8 n - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);: o1 c0 X( t$ d- g5 D
- ! A8 d6 ^6 `) I. {2 m7 e( E$ Q
- #region 消息处理(字符截取、消息转发)
. l! |5 H, C. Q4 j - try U6 d+ l2 N; {" U4 s+ \/ K# s
- {
# U+ s( V, [( i - #region 关闭Socket处理,删除连接池
4 X/ Q* d' i# r - if (socket.State != WebSocketState.Open)//连接关闭
- I- Y! i% ]+ M: ]% o - {6 x2 X4 w" O3 ?- T% r' ?( s4 n
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池2 J! R) O/ A1 S( ?- v e& J$ a6 `! j% T
- break;
) C4 ], s+ ^! U" H+ ~ - }
2 o% r! c$ E5 x) p( f3 f6 ] - #endregion l# `" x$ Z5 `$ T
$ k7 z1 U3 t& C1 N: z$ e- t \- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息; q' U1 m" N$ t8 G4 ^9 E/ P
- string[] msgList = userMsg.Split('|');
1 t4 E N6 w# z1 c3 j. m4 v4 @ - if (msgList.Length == 2)* O& Z; R8 \; A# o- p& F
- {0 s2 Q' T2 Q, |
- if (msgList[0].Trim().Length > 0)
5 a" i. l/ ]& k" T) k - descUser = msgList[0].Trim();//记录消息目的用户
9 S' b* S" o- S - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));8 E% r Q9 p+ L, B# o, J; Z
- }
* q6 ^$ `! i" b! n8 j; W1 _ - else
1 i3 z6 T5 Z& m# Z: m! i: }: H% S - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
# P; K2 [+ A, M f - / X6 ?0 L: }+ s' G
- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线0 w! w) o" |6 g/ I9 X |) `
- {6 L% e' I* ?2 N8 ? ~$ u1 A
- WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端2 g+ j1 j4 W8 u1 q- O* i7 i
- if (destSocket != null && destSocket.State == WebSocketState.Open)
% D$ e6 k- T* `& Q+ k - await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
. V5 V" n* [" c1 y/ g - }4 O- w f6 P5 p! X0 o' @" x
- else
: u# f2 j; F" J) Z3 o1 V$ t - {8 @" M9 l; a2 g% s
- Task.Run(() =>, ?4 T& F: J- ?- j: L% X, a1 F; K- }: M! l" m
- {
. U. G9 O+ B7 ]8 }5 }) ^4 G( S1 R - if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
0 N' P; {% d9 A) v' ?& s - MESSAGE_POOL.Add(descUser, new List<MessageInfo>());+ H) Y B5 B2 ^0 \
- MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
: H( E7 z9 e* W6 W4 c1 v- @4 b6 v1 q - });
. c0 }7 q( e( `8 A* z- M! j - }
5 ?' q+ K. L/ m3 k5 ~, t6 @ - }3 I! w1 C/ L9 }4 z
- catch (Exception exs)0 \4 ]/ Q" e# [/ N
- {( G# z5 ?) J$ H: x2 Y! b* j4 @
- //消息转发异常处理,本次消息忽略 继续监听接下来的消息% n5 Q- d7 y' R3 |6 M: f$ e# Z
- }& m+ K, i, m! J: [* D9 K
- #endregion `& P" K5 P3 J. J& e& X B
- }) @6 S7 }) u/ g( ~
- else
& ?/ ]4 Q9 A5 D2 d. x+ R9 } - {5 r, W5 `+ j0 J _9 A9 [+ a. V
- break;; h) O% S7 h5 s; J1 I) [( d9 z6 T
- }. c g5 t$ h0 x, J; L7 G. z
- }//while end3 v# g' `* w! j3 v$ G0 o+ [0 b
- }
& P; @- C+ b; s* }( k - catch (Exception ex). f- C! Y8 x/ W- G. P1 u
- {
& a/ S |% k* a+ H - //整体异常处理
& `9 H& P( W, }5 a; |, u - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);. F8 ]2 X7 A7 j; N$ @1 E
- }
, l0 w- |7 n3 p8 l" ?- P - }
$ A0 I- k7 u% G) \! p - 9 r, ~( f1 r/ V( A2 `
- ! E. D; @, D k
- public bool IsReusable: d0 _+ @) p7 c3 \. g" O7 ^* y8 M
- {
! Z- d- S. T8 O1 X: f - get
4 R7 E: d2 v6 `& C k3 O& A8 C, I6 ^ - {' L5 W9 K5 ~0 q! D
- return false; F& j; o+ w* L4 ^# A
- }* i( F, @/ |3 J& e- j
- }' ^; Q, H8 e+ v$ S( j! [
- }
7 t! m+ \8 f4 ^/ A+ M9 z - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
+ C% z- J* A) g- P/ h' a6 K
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |