cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
s7 D7 \4 d9 k4 A; Y% ?
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;6 u9 ^' [# R: V
- using System.Collections.Generic;
0 C/ y, D, G$ V/ i) Q4 c6 i) a7 E - using System.Linq;
5 _, E3 j$ S5 e# d - using System.Net.WebSockets;1 k! h2 A" C4 v5 ^6 z
- using System.Text;) s: S7 {, L2 E4 P8 f
- using System.Threading;4 b' r! N8 N' s$ w+ v4 W" d
- using System.Threading.Tasks;
- D4 Z. x! p) j - using System.Web;9 s# _. y* f- u# d* T9 z6 D
- using System.Web.WebSockets; H. }9 e, H1 T7 s' i
- 4 C5 `0 J3 B/ K, D0 Z
+ C, }* ^6 r5 j1 p2 m+ E: c- namespace WebApplicationWebsocketHandler# b, F' ^& x. u2 I+ D7 f
- {; g/ N9 g; `! f# r N4 Q) q; x% E& v
- /// <summary>
( W6 z- o, l& v- g4 @& e4 V, } - /// 离线消息$ s* Y5 o* f8 g+ E6 N6 t
- /// </summary>4 ]5 G0 U# e: K2 C& q
- public class MessageInfo
- E, s* M3 c: w5 _ - {! ?8 w" }' i% j& [2 ?" D3 f8 z+ J/ Q
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
' j6 e7 ?( j6 a3 P% A a) E - {1 \5 F# M9 |- u$ y& V8 W( b
- MsgTime = _MsgTime;
. s! t! U L- X/ @ A. R4 z - MsgContent = _MsgContent;) x% T- N, T' Q& T3 l' ?: n
- }
2 m4 C7 _' v& v$ S H( b/ V8 ^6 V - public DateTime MsgTime { get; set; }% J6 @" q# ^9 s7 a' G9 b" i7 y% Z, z
- public ArraySegment<byte> MsgContent { get; set; }
$ V, F& P: A7 K5 F1 ~8 i8 L - }* S9 Y" v4 E; N2 ^& @
- " f! y# r# z4 ^; a
; ?8 d8 e7 c" T% J; h7 i: R- 9 v( S9 f6 O: C7 h, l' C/ o
9 W+ \2 G4 G$ d& r! a' u/ E+ X- /// <summary>; f$ Z# e% E0 g5 |9 }. B/ _; a
- /// Handler1 的摘要说明. A4 h9 _2 n+ Y5 }
- /// </summary>
) Q+ m1 C" t/ V- W6 f( S- [3 L - public class Handler1 : IHttpHandler
" K. T* g5 ?3 }2 v, ~ - {5 J/ E( l' K& @
- private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池9 x) b9 x4 t% D5 ~9 O* F. f
- private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
7 ? V3 |( t& n/ C& o8 B - public void ProcessRequest(HttpContext context)2 d4 n+ S+ C% K
- {. s( i3 R1 _. k
- //context.Response.ContentType = "text/plain";
) l6 |; u7 ^+ }) _) G9 F - //context.Response.Write("Hello World");
& O1 I+ G9 H. ?6 g2 } - if (context.IsWebSocketRequest)
, T/ @2 p9 V7 u$ ]1 v - {! e5 z4 s" Z2 Q6 c7 ` S b' A1 @
- context.AcceptWebSocketRequest(ProcessChat); I4 Y. V5 H: m B3 }
- } 2 m" C# N Y$ _8 k9 }# q% G& Y1 c
- }7 S6 r' {6 y/ k. j+ z
- ) V! c0 p) ]: d/ R( O
- private async Task ProcessChat(AspNetWebSocketContext context)
, N. M# l; n. c2 t' }: q2 m - {* G; |' R/ s! f+ E/ [' I" q$ Q
- WebSocket socket = context.WebSocket;
( F5 V2 v( ? O% n4 {, }# m9 { - string user = context.QueryString["user"].ToString();4 M/ @) P8 ?& n! [
- " K5 A5 \+ Z4 Y( n8 y8 A- j) Z
- try
+ C' ^' d7 a2 Y$ S; g& z - {% @, d8 ]) K$ n2 m8 @
- #region 用户添加连接池
* Z8 e( E# r, P3 B* N - //第一次open时,添加到连接池中
( c4 z; p7 Y( A1 j; n' G - if (!CONNECT_POOL.ContainsKey(user))) Y h4 z' c1 F
- CONNECT_POOL.Add(user, socket);//不存在,添加, K f) z0 j3 g5 C. E7 ~
- else% M. B: C# V6 t0 z P" h
- if (socket != CONNECT_POOL[user])//当前对象不一致,更新! p+ B, {- g, o I, {( Z* {
- CONNECT_POOL[user] = socket;; m. R/ C6 G9 Y
- #endregion/ M* i) @: y# T7 |$ A0 o8 b
- 8 S* k% Y/ q, `
- #region 离线消息处理
0 \# m. B/ z! o. @ A- k - if (MESSAGE_POOL.ContainsKey(user)), U8 m5 h5 I6 i8 Z3 t
- {
# m- u7 G) C0 ~' g, B; | - List<MessageInfo> msgs = MESSAGE_POOL[user];: r8 b! L0 T/ M* N* q9 v \( \
- foreach (MessageInfo item in msgs)1 Q- c3 z8 Y) H% G8 x$ M- h7 w) X
- {. Q6 e3 M' q4 S8 U' Y9 l
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
$ T6 C* z3 ] _ R: Z - }
. U y F J* h/ l - MESSAGE_POOL.Remove(user);//移除离线消息6 l: C5 ~2 _* ~# R, m A
- }
" d% E" U' }) P% C2 s. A/ T- a2 j0 f+ O - #endregion( s3 y8 y: P% L2 \, Q
- ]& E" e) ^2 h1 r3 l* j( d/ a
- string descUser = string.Empty;//目的用户6 h j' p6 p t- }: j; L" z
- while (true)
# f4 P' v F3 x' n3 v( b - {' b4 O1 H" c3 [" B# [
- if (socket.State == WebSocketState.Open)
/ o) d {9 s" r9 G7 t - {
8 x. e* x0 `- a' x# _ - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
% ?1 `1 A' ~) m: C - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
# w3 O8 X0 R) @) b - 4 N/ _. K, a5 m, y% l
- #region 消息处理(字符截取、消息转发)
L2 P3 }4 J$ J4 o3 M - try
& f& R( T& h/ X - {
7 V3 W* \& s# I. V- V - #region 关闭Socket处理,删除连接池
4 L5 |7 m- V6 v/ h1 v( |4 Y: m - if (socket.State != WebSocketState.Open)//连接关闭
: V3 l7 s) E2 J5 B0 b5 M - { N; k# J6 L2 _
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
" Z/ s( H: n8 a# F% G0 [7 ~ - break;
0 A1 |5 _3 ]' c8 o3 M, v& ^ - }2 _/ @- ^3 ]- q0 z
- #endregion& x3 a$ k- y& S) ?2 D
9 ~7 w/ E) k! l2 D- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息( L: ?, [6 R" i: ?
- string[] msgList = userMsg.Split('|');
& s$ m9 V2 m# ~1 r) B0 X - if (msgList.Length == 2)1 G% F. N0 H2 n5 Q9 C! P
- {
* A+ c( Q' m: u, d - if (msgList[0].Trim().Length > 0)3 A$ x' L3 k8 ?& S; G
- descUser = msgList[0].Trim();//记录消息目的用户3 \# c- G) l$ R' {3 A9 a
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));! l9 P/ J% ^! n! [8 A/ e1 A
- }
( V4 s, W9 [( @ - else
7 A2 Z# l6 L* E1 h! H, { - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));3 M% S: H& ^7 w, d
, R# f/ c: N! y! v$ I1 u& I- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线+ Y V4 n* l; L) \2 Z
- {
* y V* K5 b( t$ M; C& i: e - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
2 J6 H, j( L$ X9 p, J6 V. k - if (destSocket != null && destSocket.State == WebSocketState.Open)
8 \3 ]0 ^: m8 i* ^: ?8 Q9 z$ g7 A - await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);, q( D. ^& q4 v0 y/ Y8 C
- }
+ J8 B; y5 Z) e9 q& A- _ - else
5 s, W7 `4 t7 Y; q- g9 J - {
+ N- N. U3 M8 |7 y: z - Task.Run(() =>
! x" q, C W& C9 h( N0 y% ^ B6 S4 } - {
- T5 `3 w' X4 [) \ - if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中8 f1 ?! u3 d9 a% g
- MESSAGE_POOL.Add(descUser, new List<MessageInfo>());7 b; p. u$ G7 A8 N7 h# l( Y
- MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息% Z( y5 t2 V* s$ ^# V" x! M
- });
3 g' n( B+ d: R) | - }
* Y& W; G5 v# t8 ~. z4 C, U4 I - }
1 y. C( Z' ^, s, ]1 r3 w - catch (Exception exs)% z+ U% f3 J2 z. ]6 z9 o
- {8 I) W6 ~/ R: ]6 y$ N
- //消息转发异常处理,本次消息忽略 继续监听接下来的消息
4 t3 W. m( G1 C O - }
2 k" R) n2 `& S! n% C' M - #endregion
) m3 A& a$ p# M4 u% Z - }
$ z# u. `9 X4 z. W7 K - else9 I% x) c2 l& a( z3 A! |
- {- \6 O4 p$ Z2 q& X
- break;
/ R- i7 z% r4 r) ~' }! [ - }% f/ i& a( `2 {5 e+ H$ P, ]. v8 C0 D
- }//while end
# f( B2 s* F# B: R - }+ Q( A+ @8 G# e+ _* i
- catch (Exception ex)
5 t! C( i; [" p5 \+ R( M - {, M( F( h, e) j/ z1 u& N9 s
- //整体异常处理
; [8 `0 |9 b9 f/ e+ ^; |* P6 y4 R - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
, h* a ?; \/ F6 e0 _' C - }7 s2 `7 p; R' V
- }( p/ ? t4 ? g6 B
- 3 \: R. w) \$ J3 b
- & U {* I6 R; I
- public bool IsReusable
6 Z Z- r7 V# [5 z. V" u! U - {
6 G& U, B1 I" r0 S4 l+ E, m - get
' u p Q8 e2 X/ O - {4 z+ R" `. g2 n7 Z" e' J# a! T
- return false;
# M: p3 F2 m5 G$ Z' t - }, m* M7 d$ O6 n. }
- }
c% F/ h0 ~- R1 G# y - }
& z! F8 X: s4 Z! ]; r9 G" i - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
B" ^ J) y2 }1 p) K9 S
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |