cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
! _3 [: `6 V b7 x2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;
9 _+ O! y0 v: |* x! O c - using System.Collections.Generic;
3 C$ B3 y. R8 s - using System.Linq;
5 S; B6 S/ B, Q" _8 f8 P - using System.Net.WebSockets;
+ B. V1 W( f+ \. P - using System.Text;; s3 J9 A2 g% w5 L6 i6 v
- using System.Threading;$ U1 `1 s! J2 a- R. q
- using System.Threading.Tasks;
/ r* N" b- E8 a8 A; A- U1 { - using System.Web;
T1 P X" F( ~7 x0 P - using System.Web.WebSockets;; _: g" L7 M+ H* c% y
- 3 Q: F( P' G( J- Z, o+ S
- 3 U' u5 p: _6 a) W% X
- namespace WebApplicationWebsocketHandler+ L1 r1 [ m* e4 w
- {
0 U% o2 V( x! e3 l - /// <summary>
7 @; ^8 J; T( z: m v; J+ n - /// 离线消息, I- A! l7 }5 @4 C1 i& `4 [* T/ R
- /// </summary>% \% h& B6 W. ~$ t* R9 g4 Q" ?
- public class MessageInfo; m+ o# `# ~4 I3 B9 a" e
- {
* o1 \! B' d$ U" o4 O4 C - public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
0 O( D' d. l; O( Y8 p5 Z - {" L8 U" Q5 B8 ?
- MsgTime = _MsgTime;& S0 v+ R- `' r$ O4 t" Y* h
- MsgContent = _MsgContent;( _* ~$ |7 I+ J$ q* X" C4 @
- }
% Q8 T! ]6 v$ }9 t$ `" I - public DateTime MsgTime { get; set; }
" N( k6 H: Z6 f4 ^0 { - public ArraySegment<byte> MsgContent { get; set; }( \, d" }9 w, c' [7 v2 L
- }
7 T# a4 a' h: d: l3 e! @
, r: O9 s M$ T! r
9 B# P5 B9 H4 x4 `" m- G& E. I$ e
, n& i! o( P0 w2 u% a- 6 L" `7 T7 R9 K: m6 f2 t& v1 u
- /// <summary>
+ [% E0 B2 ?+ {" v& F - /// Handler1 的摘要说明
G1 p: M" O: u/ n3 d$ z F - /// </summary>
s3 ^! n/ h2 G9 J1 [2 {8 x: n - public class Handler1 : IHttpHandler
: ?; x( T4 W8 w - {- y0 J3 C8 Q; V
- private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池9 W; K; W3 g5 f2 {+ j7 q4 V: _" E0 O; B
- private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
; r/ |, A/ p1 R3 T/ o/ {4 `% Q - public void ProcessRequest(HttpContext context)
+ {: _- \$ y3 I/ x( K5 Z; y - {- S' R8 r# ~( d; u, X
- //context.Response.ContentType = "text/plain";
2 j! l& O, I6 v/ e1 S, J - //context.Response.Write("Hello World");
4 Z5 l) l, E5 B* R' j5 g - if (context.IsWebSocketRequest)
w; U6 G5 m) E% H - {. y8 H0 d5 f7 ^8 g: o
- context.AcceptWebSocketRequest(ProcessChat);
/ D; ]4 v: [! l+ D- A8 B; { - } ' [5 k8 ^/ {' x
- }+ E! G- S/ v1 t! v
- / ]+ }& D$ J' f0 f3 _
- private async Task ProcessChat(AspNetWebSocketContext context)) [1 I. M6 G' s) [, O. t: ^ a
- {
; `/ a; {- P4 G, @1 @ - WebSocket socket = context.WebSocket;
+ B5 x9 ?" w6 [$ F" H8 m6 |1 N: h - string user = context.QueryString["user"].ToString();. G3 L1 c% @! X% F" U; }
; `: u. U! v0 J7 W$ _- try( `4 N9 \- a$ R3 v/ @/ {
- {
: R) `: v0 Q" _* q4 m" W- J$ ]' { - #region 用户添加连接池2 i* l/ n8 V3 \3 j. p3 }0 }
- //第一次open时,添加到连接池中" b" }1 }* G' @# y
- if (!CONNECT_POOL.ContainsKey(user))
. F* c9 e7 _; h! l - CONNECT_POOL.Add(user, socket);//不存在,添加6 ^! c( I3 _& c& E
- else# A; B: _6 K- `0 G2 b
- if (socket != CONNECT_POOL[user])//当前对象不一致,更新' J1 v+ j/ m* U/ I/ H3 [
- CONNECT_POOL[user] = socket;
. \7 x5 _" \8 W+ U1 L, b: h, r - #endregion: I' g4 z7 A) p0 s0 a4 x
- 3 t; o7 X/ R& e6 G- f/ R% L' k
- #region 离线消息处理- l) y1 m) y# d
- if (MESSAGE_POOL.ContainsKey(user))
7 R8 j3 S( j' G; X - {
9 c/ A% g! e; J' O( P! Y - List<MessageInfo> msgs = MESSAGE_POOL[user];
# ~7 m7 Q+ J9 X/ w - foreach (MessageInfo item in msgs)
& V$ l' C( B8 m' L; p4 K - {
5 t. r6 l9 F: \' z& u' p - await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
I; N. G: f* K. _5 ]; f - }
/ d; z) H) q% L3 I% F$ ^: O: v% v2 g - MESSAGE_POOL.Remove(user);//移除离线消息
2 m7 ]+ h# c7 @ - }. A5 p. j& }. e) T: n
- #endregion
: L4 J8 k0 L$ G& Z5 M9 u/ P
' g. N7 c, P4 R, |- d- string descUser = string.Empty;//目的用户 }2 |' F9 a; y1 w5 M
- while (true)
9 G! @3 q$ k1 Y# v6 A" E s; J$ ] - {
6 P7 }% G/ C# G - if (socket.State == WebSocketState.Open)" [' P# m0 ` _( R$ V+ |
- {
6 ~* @0 b" {* G% I+ {) A - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
& V8 E0 l% b9 Z6 c! o2 e4 A - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
, ], x7 L0 `1 L3 X - 4 A' H' g. ^" y+ y
- #region 消息处理(字符截取、消息转发) s; e" r- j, ^8 g- }7 p
- try2 n4 ?" |& l+ E+ Y: b
- {5 A0 Q( ?4 Z& J& e
- #region 关闭Socket处理,删除连接池! A- i y l6 J9 w- s
- if (socket.State != WebSocketState.Open)//连接关闭
$ `; e/ i( O3 k' u' \' L - {
( {0 f1 C- `1 [: Z$ n) T - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
- O$ F4 c( j/ I' v - break;4 @( M" U; R4 P A" q" ^
- }" Q2 A/ Y- C6 y( k O$ |7 ^9 F& ?8 u
- #endregion
) L! s! Z; L. ~( u. P: K3 Y - 2 b! { F% I6 {: t) V0 d
- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
# {1 i, M T( Q2 A+ M/ y - string[] msgList = userMsg.Split('|');! }! s- r; n& o m8 F, t9 m
- if (msgList.Length == 2)
. O* j1 c6 B' q6 y: z* O - {; I/ h, o2 b) H6 I6 K" P
- if (msgList[0].Trim().Length > 0)
) i( X. o" ~" y5 J - descUser = msgList[0].Trim();//记录消息目的用户" ?1 L2 Z# i" }2 a/ D2 w
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));* }* l9 W- e% v" ~
- }
& D$ h( |# p# o- E! e, f5 x+ [7 } - else6 ~- O; b. R [
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
: Y' i6 ?2 \$ \" [. e6 @9 _
0 l4 X; R( L- q8 O- s& M+ b- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
% d6 I, V+ T, N- ? - {
* J. x& H; {0 O- E4 l8 r/ E - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端- ~5 Y6 _0 Z; \8 i) ?; f
- if (destSocket != null && destSocket.State == WebSocketState.Open)- c& w; S1 O, \& Y) `4 _
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);% Q+ k4 t$ y9 {. m
- }
" s9 ?+ N! d5 G( J6 `! p - else
& b8 W! S Z, H' {3 N7 y' g6 g - {
0 A* @% W2 i% D5 z0 | - Task.Run(() =>% ~$ I- a% k0 C r4 w( V. I% p) F8 T
- {
" f$ ~# [* i- D9 e9 V& F - if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
# W/ ^9 X2 {. H- [ - MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
2 r; v9 }) `9 _ - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
/ C0 S3 h4 \6 a+ ? - });
) p$ r( l3 Z& @: R( n - }& P; Y+ I0 b7 S) u3 R3 \! v5 z) {9 W
- }7 F8 S; W/ n/ K( D$ C4 C( }( p
- catch (Exception exs)/ e: h P$ K; f. ]
- {
. ^; l4 _& |6 U; B8 M - //消息转发异常处理,本次消息忽略 继续监听接下来的消息" ?! o2 @' H8 m, r2 R- v
- }2 u* ?7 y/ l% r4 z( R# j' M
- #endregion
: y& O; [3 ~5 `# ^6 D* b6 q - }
4 h2 D: N4 r$ y1 e - else4 E' z+ {) m7 b8 E6 y- B, J, q
- {
( p/ S/ N2 h @5 e. Y5 x% G - break;9 Y3 [; n( A# U( C* L9 a# g5 q
- }" ?+ L4 z6 o9 v ^; H' R6 {7 }
- }//while end; y/ f1 h8 S+ c. B
- }4 e; d" z3 K Y& J d* k
- catch (Exception ex)1 Z3 C i' r6 ]' v% a* x
- {6 J6 |3 A+ u. L9 f
- //整体异常处理
4 q6 P, L" p5 t - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
6 g& G, e& ~5 G/ n( h* | - }
; _- b' g" Y& ?$ { @4 F; K - }# ~" o3 J) i- S+ J) V8 x. m( }
9 m; @1 `" q/ G
) h4 {+ u t0 O: E' H1 p+ ^- public bool IsReusable! m) H) X, J: E( ?9 m5 p/ J
- {$ \$ ]# P* A6 \9 b$ s O8 Q
- get
1 P, ?( ^5 q& Y" w3 ~+ ~ - {
2 @" v8 E0 l% ^9 j - return false;
$ }! ?9 g* j4 _- X1 k" o - }: G0 M T: g" i/ X- J/ L! r9 @( Q9 p
- }
( O; ~7 i S% E+ c3 Y! d5 ^ - }
$ M4 g+ C3 P2 G2 O9 W$ o0 l - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
7 x+ `5 R3 X1 a {. S
| 欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |