cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
8 m: c# F, ^, J' y8 |3 j
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;; {( F; x% j: j7 g
- using System.Collections.Generic;
" O; o3 Q' O" W/ `8 O! e - using System.Linq;
# q% ~, F+ v; _, ]: K9 z - using System.Net.WebSockets;1 V k5 o0 n" C+ j" h Y: H3 {$ q
- using System.Text;
- v. z- u- @/ z# b! \2 p) w - using System.Threading;* t) S2 C: `. Y2 e( ?
- using System.Threading.Tasks;. x: x H4 R7 e9 k d2 h" I
- using System.Web;- O( a* r7 ` N H; i y2 u6 N. b
- using System.Web.WebSockets;" u7 D, n/ g4 G9 X
' D( l* Y1 t# l
H* D, J1 \2 L+ y3 C+ w% e* N- namespace WebApplicationWebsocketHandler, {% [. Y6 v0 I0 X/ ^4 n1 R
- {/ d& D O7 g- L2 E. z8 O
- /// <summary>+ w/ ]) X2 J- `) e y! K+ P' Z
- /// 离线消息
1 c- t8 ~/ |0 D0 [$ a- ^ - /// </summary># C8 I _1 C9 {' Y$ Y* m- T
- public class MessageInfo" B! d; a6 x/ D+ P2 u
- {
4 N2 V2 `# ]- [. V" T - public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
: j: |8 L. z, E" P6 v9 r - {
( C9 u) N9 x) ^5 z6 {( R g6 L - MsgTime = _MsgTime;' d3 Y) [5 ~) G1 y! u
- MsgContent = _MsgContent;9 q2 e |5 E6 `
- }1 j& A! B0 M7 I- n4 @7 L1 O1 @7 J
- public DateTime MsgTime { get; set; }4 K7 C3 c. ]' t8 m$ S
- public ArraySegment<byte> MsgContent { get; set; }6 H" w9 }8 d# k5 `4 l
- }
2 o. ~6 N: Z/ @" m' G! ] - % [" r) F- i0 D, J: N8 l
- - I/ N: d' T/ p& F, g" ~: v. R
+ [& R1 x0 |+ e3 O- i: _$ s( e- / {' s% `4 N" s3 r! _8 M/ h9 w" J
- /// <summary>
$ s r0 Z+ a. |+ j6 X* D - /// Handler1 的摘要说明2 A F) U' g1 d5 B6 t; D7 e# [+ V) W
- /// </summary>
4 x. X0 P3 Z b - public class Handler1 : IHttpHandler
7 A# Q/ ]( c# z$ d" Y - {
/ J& A& d/ V5 ?6 g - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
! v8 Q: s3 R! r) K2 ` - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池1 r7 K) B# V# Z) g: N
- public void ProcessRequest(HttpContext context)
6 c9 }1 T: P9 ?7 G6 ?6 Z9 b - {; r* B f3 e% F: X) @
- //context.Response.ContentType = "text/plain";4 n% g" D+ P$ a0 r9 y2 N
- //context.Response.Write("Hello World");
9 ?0 @1 C4 Y: {. x6 ?9 u - if (context.IsWebSocketRequest)
) b1 i) T& {" k* h - {6 }; a/ Q I* u) c. R
- context.AcceptWebSocketRequest(ProcessChat);
# b+ \2 n# o- }5 c) ^ - }
* ~3 Q0 \: J0 q0 Y1 U3 b - }9 w" S- {1 K4 `8 l, h* v
- ! b7 Z3 S) V I0 H
- private async Task ProcessChat(AspNetWebSocketContext context)2 l% \ n9 K2 Q2 f& `& F& n7 C; ]
- {
4 c/ L s9 Q, q2 {6 d3 i# J - WebSocket socket = context.WebSocket;
4 R3 |* |( v. ?9 N) \/ w - string user = context.QueryString["user"].ToString();
. a! H' N$ X' O2 T. n' g8 Z - * n, ^8 z- J# } T! y" Y% m! ^% Y
- try
0 d/ ?) p2 F3 d - {. X* N# S, [: C8 f: L$ a
- #region 用户添加连接池
( @: r) I1 r" | - //第一次open时,添加到连接池中# n: \3 D+ y" ^8 v+ C$ p- G
- if (!CONNECT_POOL.ContainsKey(user))
4 B8 H9 Q9 x. y F5 a - CONNECT_POOL.Add(user, socket);//不存在,添加9 H$ u5 q$ {' g: K) y
- else6 @# [' V; J2 R2 h5 d/ l+ z @/ k
- if (socket != CONNECT_POOL[user])//当前对象不一致,更新! S% @, i- d3 J% t1 ]( V. T/ E
- CONNECT_POOL[user] = socket;
2 K; ^2 U3 B/ t0 f& w - #endregion9 j4 d( p* `$ ]3 G) B4 L/ H$ Q1 j
' ~, h8 l; T! x. Y( g) m6 P1 ?7 }- #region 离线消息处理
) I6 i/ J6 r- O% _5 y3 w - if (MESSAGE_POOL.ContainsKey(user))3 L1 c) |1 n, W b
- {! N& U, @* Z( R. I0 {) Y
- List<MessageInfo> msgs = MESSAGE_POOL[user];
6 _, P5 U0 a0 d6 Z- h) r - foreach (MessageInfo item in msgs)
& _5 z: t% @! @) F - {9 t: z5 C* z- I ~! ^
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
/ v6 `" D2 o. e; O6 j - }9 ?9 w" Q7 }/ W+ H! K6 i/ D5 Y/ ]2 Q. N- z
- MESSAGE_POOL.Remove(user);//移除离线消息
4 s- z/ g0 J& o2 l - }
5 p: c; [( T5 e% w. a' ^5 F' T - #endregion
1 {6 n7 f4 D) S+ o$ O. P
" `1 `8 X6 l, X# o& k- string descUser = string.Empty;//目的用户
( {0 \ G4 D# s5 ^! L5 e - while (true)/ q5 h' x3 o% K' z5 [
- {2 P5 N/ y2 r& E* S
- if (socket.State == WebSocketState.Open)
6 |6 o2 K- o" M" t+ X, k5 P - {2 V) X* F4 ~0 _0 r
- ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);; ^* n2 r, F6 i1 B7 ?! \3 `9 D
- WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);0 D1 [* S% q# T0 v- ?9 l
# V9 O7 E% e2 m: u; z3 l- #region 消息处理(字符截取、消息转发)( k$ l0 n5 z/ ^" ]8 p0 ~
- try
7 N+ v2 f+ V3 F7 }* \6 W - {
8 j A' J- ^0 E0 {$ A0 D6 L. I1 { - #region 关闭Socket处理,删除连接池
9 P# J$ W0 C" x+ S" c3 g - if (socket.State != WebSocketState.Open)//连接关闭0 u( N: j. J( R+ c" Y/ ?
- {
8 p3 n2 H; k0 e5 W# w - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池0 O* I* O% a. N2 U C7 y5 |
- break;
8 |- T* V1 T" ~4 L - }+ D6 ^, ] u) R( `, E& z1 ^8 F
- #endregion. z# d* Z7 w* p! E1 Q
9 b& g' m1 N, z. z. Y- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息. J/ I! ^' b# p: S
- string[] msgList = userMsg.Split('|');
0 [' q) w7 H# y - if (msgList.Length == 2)7 u, l" q) j, O7 I
- {5 Q3 p. w$ U1 {
- if (msgList[0].Trim().Length > 0)3 g3 I; N5 y, U/ m3 r0 B
- descUser = msgList[0].Trim();//记录消息目的用户; O+ C2 K) G0 {8 n A6 F" a
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));
/ o! W: f9 ] f. g% W2 [4 g9 Y - }
9 i* j9 I9 q+ z3 k+ B - else- e' y, E/ N7 h- h2 s
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));5 T3 N) i2 v. s0 C
* a! M! X6 t: {6 e% w4 t- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线' w+ g! Z8 t/ B' }
- {- [5 F* ]; Y7 q& Y
- WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端" @9 I- q) {6 f8 w
- if (destSocket != null && destSocket.State == WebSocketState.Open)
2 ^3 m, s6 p2 @) X3 Q- N1 i - await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
' L9 z/ B; a0 p) }+ q8 L - }% F) W9 N( f- \7 K- O9 A
- else2 }# k8 \% i) t$ M0 H/ i
- {" Y- v) H6 I/ d6 U
- Task.Run(() =>" B" `( Z3 J+ }3 g' R5 ^& R
- {* _) N2 w, D4 S8 ?2 M( K* |7 ]+ X
- if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中9 y4 d# D3 e; ]* i( S
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());! _. G3 G7 y( Z& P* Z" P$ D
- MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息& z1 L+ u" d! O
- });: Z7 |8 K; c. k
- }
u4 H; w& y7 I8 y& S6 L - }
/ ~, r: E7 t; d" B. h% u - catch (Exception exs)
# }& o# O# C4 q# v p! j - {
+ F, |; S: ]1 R; O0 r" _" c - //消息转发异常处理,本次消息忽略 继续监听接下来的消息 r8 S6 T# ~8 @- G* e+ D
- }
* z( |) r. T# Z! R$ W+ @ - #endregion$ w3 d( L, F- Y' r* U5 z5 c3 X
- }+ \5 ]; c2 Q/ [2 G3 Y
- else3 O8 P) Z5 J7 R3 f4 n- u' _3 q
- {
0 g/ I# @! ^4 q. B' K - break;: [8 z7 L* S) [3 O l, U) J
- }6 J( z1 R, E- L
- }//while end
: T0 o$ A7 C% L7 t0 j) z# I - }% u' e( b" [4 m1 h( |
- catch (Exception ex)0 k8 Z* P! j3 b$ ?
- {3 o5 i u, t2 Q
- //整体异常处理
7 K) O h/ Y8 S/ Q+ U: ` l - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
) B+ `# o) T4 Q, f3 d - }, E" K2 J" e5 H; ~) c2 d3 g' `# g8 h
- }
7 U! }/ o' ?! i7 z! y - 1 c' y: w4 |/ o3 Z
- 8 j+ T! l' o) y) u U, n& F
- public bool IsReusable
3 y/ X; y. R$ v1 ` - {
4 V3 \- S2 `& l6 X8 n - get8 D- O6 J+ a: |" r/ A
- {
- V* x+ k7 e5 w - return false;
+ K6 r8 g c2 h, v3 r/ ^' } - }3 W$ M1 F8 p2 \7 O `
- }
5 ?& V. M. k8 ~ - }6 h3 D3 a9 h7 i
- }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
. T% e2 |' Q' B5 a7 }4 Z- M, W, [& Q
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |