cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
. s+ d+ L* g; E& U& |; W$ g
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;% h; _6 H3 f4 r$ h
- using System.Collections.Generic;
8 R" R5 m$ C! m a! E/ Y - using System.Linq;) Q* S/ h6 x% B& |2 W) Z y
- using System.Net.WebSockets;. A& `- t% C* W c% z8 X; d
- using System.Text;7 n" b3 N W. b* L0 K% N
- using System.Threading;
. m% l, f( U+ Q- ]6 ?" g; T - using System.Threading.Tasks;
" q5 T" @- x6 K$ j* Y+ @4 A - using System.Web;
9 n: @& h: b% x2 _8 h0 j - using System.Web.WebSockets;
9 B' i+ V+ |( a3 D - ( A- D' c4 I$ y* a3 j
- 1 T4 d# P7 P; f" n: e- B1 h0 h: u
- namespace WebApplicationWebsocketHandler! n- @; V# E) G1 _
- {# _8 h$ C- `8 n0 t; H) L. ]
- /// <summary>
. o) w! k; Y8 _; ]( t% ]* N - /// 离线消息
) `0 f* t2 \) \/ {3 Z c1 m - /// </summary>
" Y) t/ H+ Y, v, g) @7 ~* i! s - public class MessageInfo) f/ n* Y7 W0 ]; a
- {6 A# o( e: z, S; v1 G0 w
- public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)0 f/ a8 Q9 ^! f7 ]: {& c3 }
- {
; p# `6 i3 f+ ^6 U6 I! F$ d - MsgTime = _MsgTime;! x2 V7 ^+ M' \3 F7 m) Q0 C7 r
- MsgContent = _MsgContent;2 ]. p; I& D+ `! U
- }6 I6 f/ O2 m8 M! x; |8 a
- public DateTime MsgTime { get; set; }
- _$ a( x# Q2 q* P* h! h9 Y - public ArraySegment<byte> MsgContent { get; set; }1 w5 l! e* E! x* t
- }
$ N' o# x9 G7 ~6 ~: h - - I% }5 u& C: s9 m
4 |, p- W, l. x& J7 O* ?6 l
& P8 h m5 _/ }7 U- / `% ]. f2 y+ V$ O/ c3 j! f
- /// <summary>
3 d5 k" v' R# A4 f) T7 X - /// Handler1 的摘要说明
t4 b) y% g! E) q& G8 t) [$ O; M1 G - /// </summary>
# G, ~$ G: k" a- E, z* H3 K7 r - public class Handler1 : IHttpHandler8 ?+ K+ x2 ~' d4 ]6 x( i# x
- {1 p4 e# A2 m5 p
- private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
4 c: y6 O1 U3 w$ \: L t& ?, s' }, i - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
+ ~2 E6 U: ]8 {- x - public void ProcessRequest(HttpContext context)
3 W& W2 W v5 E, r! Q2 X1 f - {
4 ^9 k8 Y/ }9 V - //context.Response.ContentType = "text/plain";
- j H" N- Q" M2 } - //context.Response.Write("Hello World");$ Y0 I' h" p+ ]. a9 O
- if (context.IsWebSocketRequest), X- {) K4 ~3 D$ o+ B9 E8 _+ s; K
- {$ a. o; |# O( m n$ D; W9 u- d
- context.AcceptWebSocketRequest(ProcessChat);+ y p# I! m; i
- }
- ?& G, x- c# z" Q - }# b1 G% ^8 c$ n. N4 s
- C" I# o% i, c7 B( J2 f- private async Task ProcessChat(AspNetWebSocketContext context)
, ]. L1 c9 t+ z! t3 W - {. n' K0 m7 Z0 D& [& H w
- WebSocket socket = context.WebSocket;! H+ W: S7 G5 S% G0 G& W) D
- string user = context.QueryString["user"].ToString();
# H. d7 D5 N2 F0 [: V) C) J8 O( k - 8 \, }9 H# z: E M ^
- try
5 m2 }0 B; c+ f; C8 e - {' h+ t2 o$ n5 X7 W6 C
- #region 用户添加连接池
) l; L3 X; ?* k4 q - //第一次open时,添加到连接池中5 {% L- Y" _/ R X( d& K
- if (!CONNECT_POOL.ContainsKey(user))
3 Q9 L {2 l1 D- ] - CONNECT_POOL.Add(user, socket);//不存在,添加
- b: } P7 c- j5 Q7 O2 S1 Z6 B& C - else- m& \6 k9 N$ T# o7 i6 q& \' F, H( |. K
- if (socket != CONNECT_POOL[user])//当前对象不一致,更新
, C/ m+ Q0 X. T7 F$ j8 \ - CONNECT_POOL[user] = socket;. ^9 p" @1 D3 ^! r1 {& P! r
- #endregion
* g3 h; q& u P5 _4 l, Z( b) ` - 8 E! X2 Z K1 G M% G1 x
- #region 离线消息处理9 n! l3 z* o9 [4 c9 o
- if (MESSAGE_POOL.ContainsKey(user))3 a$ l9 |% K6 K0 r- z) u# H
- {+ s1 s) X6 }; |8 V0 S
- List<MessageInfo> msgs = MESSAGE_POOL[user];
3 B- Y& s6 ^; Y& O1 e - foreach (MessageInfo item in msgs)
/ M- V# l$ f7 {' R2 A - {
3 w3 V* |" l& Z& z+ b. g5 m! @ - await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);$ G* u* ?& {: I6 E. k: I! W
- }
, F$ K8 o( d6 n9 ~ - MESSAGE_POOL.Remove(user);//移除离线消息8 L& x0 U4 ?3 s [5 p7 j
- }, b2 ^& Q) P' q$ f6 d! b, p A5 U
- #endregion
) K& }' D) Q8 c) l) I - ) I! E5 W2 y+ R
- string descUser = string.Empty;//目的用户
% h% R5 c( b5 o1 _2 | - while (true)7 A. A& j1 p/ }* A
- {
6 o) o. Y; b6 Z! N - if (socket.State == WebSocketState.Open)
8 w4 e( p3 J7 s1 z& c* q1 Z - {
[% j2 n J5 W5 V - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);9 ]$ }* C) W5 X% g9 F
- WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);' v6 K( m0 g; j, E1 T8 b/ S
- # j' Q9 u" |" ]$ S5 Y
- #region 消息处理(字符截取、消息转发)3 Y. l: x, Y+ w" `' p3 h+ b! a3 ~
- try
: C: W7 I+ {; Z: G( l: D* P1 W0 W - {
$ x$ \2 ^6 t2 \5 G3 q - #region 关闭Socket处理,删除连接池
4 h* B9 J3 U. i" i - if (socket.State != WebSocketState.Open)//连接关闭
0 z9 P% Z9 B- l. Q' E - {
4 q4 b/ P4 K8 w, k1 i - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
! |+ [0 p# N% n! A; k8 V - break;
/ ^$ ?) K3 T0 l D- {6 q$ v0 L - }
* x* ~8 B8 ]+ n7 K5 b - #endregion
* O) |& D: I# _. `
+ p/ A) `5 ^7 D6 m, j- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息% d0 K/ w9 O" V i& j3 N
- string[] msgList = userMsg.Split('|');9 U( k: B* \7 T7 C6 b/ j& H; E
- if (msgList.Length == 2)
" @- p! t( k7 U - {
) ?- k& `" x0 n8 U# Q! G0 _7 J. o; `7 \ - if (msgList[0].Trim().Length > 0)
' F# G# @5 Q. r! U% ] - descUser = msgList[0].Trim();//记录消息目的用户7 O9 @/ m, ^0 \6 s0 q5 {6 M( M
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));) O3 S x& I: l W) [
- }# N1 E% k; V, A( c7 J: D. g( h+ v
- else" ^2 r5 {1 T" G2 I7 N- s4 A! y
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));. a& j9 h1 d% j2 C2 @4 W
$ K( m8 o |% \' x& ~. S; J* w, w6 K- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线4 q2 A7 {7 `' p
- {
/ J% R# G! I. g( ~ - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
* h* H1 A2 B& g9 | - if (destSocket != null && destSocket.State == WebSocketState.Open)8 K3 q5 \% Q* p, V" G* h, s- [
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);1 M' g3 p7 ]6 `
- }
' F% h3 i- u( v2 u' D' k - else) i5 k: J- S7 {+ j7 F3 S
- {9 o- T; \7 [- n+ }. C: c
- Task.Run(() =>9 i; W9 [8 l8 M0 F2 n& [7 |+ u
- {
8 n0 p$ d6 N1 z: P1 U ` - if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
! \; @- v* `' I3 y - MESSAGE_POOL.Add(descUser, new List<MessageInfo>());! P$ T) E3 Z" B* u8 @- i
- MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息" v6 s1 O$ ^. v2 m4 b! W G8 ^' T9 \
- });
4 Y0 O9 h3 F- D! ~ - }
. v4 q$ X) l* w2 m9 [ - }
+ \+ I. Y1 Z5 `8 j( N% Y8 F - catch (Exception exs)
/ E' L# R+ G2 ]! z - {
3 }4 q+ b# t: I7 j - //消息转发异常处理,本次消息忽略 继续监听接下来的消息) s$ G# {1 g. K, Q2 b" ^
- }
/ A3 T( h# ~( ]( r9 k: q- N4 {' k- z4 n - #endregion
8 a% Q, h* v8 e0 T6 l. d - }- d5 [1 ?0 n1 z* x7 S; K
- else) j. a# w! L0 W0 k" t- w
- {
8 V" W& T* R2 H1 w - break;. A5 T, `% K" _* c+ t9 w8 d# S
- }
+ C9 R" C+ A& b! y - }//while end5 d6 q, i+ M2 b+ `
- }/ S( s# d0 x3 ~- U- l7 t' ~
- catch (Exception ex)/ p) ~1 X. a# G& f& q
- {' v" }# e3 J$ B4 `$ }
- //整体异常处理
, {8 p# z; F0 [" Q6 z- Y; _" ]4 f - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);2 L9 @4 x( L* Q& g
- }) M/ k' D: p/ f, o0 d) X _
- }
$ w. x F. F$ m; ]/ G - - Y/ Z! ] b% T9 J. N5 T0 E a. z
- 5 T; H2 c! y1 J) A
- public bool IsReusable0 ~. h/ V1 f, e( s0 b9 X7 u
- {7 c8 l: r' u$ v0 A7 d" p+ z
- get* \/ f' V+ U# T) {! @
- {
p; r/ Z. s6 P( F0 ]2 _ - return false;
7 _5 \" U9 K$ N% M7 L( K - }
3 e1 \! S( W' \9 Y4 B0 @* z: ^ - }
6 L% i3 ~6 Q0 d - }
+ a: U$ u( S |5 A$ Z p% [ - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
+ d, y; w6 r. \/ T
欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |