cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
, K# T% a+ L' n
2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;
6 l; ?8 c/ n) e& C. \; \ F - using System.Collections.Generic;: E; y( a, V$ C% E: f+ U/ w( W' D* G
- using System.Linq;& n' z. A6 v+ @9 C% C
- using System.Net.WebSockets;
" D f+ ]! @2 L% j: b3 `8 d - using System.Text;! \: ~- ]" W1 M4 ]# \9 I$ J. W8 B
- using System.Threading;& K& i7 V9 @& F6 I+ g# y, H* ^
- using System.Threading.Tasks;- P# N: U! v$ ?, b4 _
- using System.Web;2 K E1 H. v4 `% F7 P4 y0 `- B1 v
- using System.Web.WebSockets;
9 y% Z r, U2 P
. O* V, E% e; d6 P8 A: j R6 T5 q
6 h* f6 g* s% v) {9 N- namespace WebApplicationWebsocketHandler
3 `" S% d' b! I+ i; V* f - {1 ~! L; P& u# W) e$ r
- /// <summary>" ~ l( S* T7 p0 o K1 E, C/ w* D
- /// 离线消息% d4 m) H' W; f& n+ ^8 e6 L
- /// </summary>8 Z6 |7 J) D% {% Z4 H1 H
- public class MessageInfo* H# F: t( v4 Q
- {
^* R1 H7 u, H! g L- m - public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)
( \: Q+ L/ ^* ?9 k$ Z+ z; F6 v - {% ~' Z+ R+ Y% `( s
- MsgTime = _MsgTime;3 i' X+ g g! T; M- \; `
- MsgContent = _MsgContent;
) J4 G" `7 Z& y5 g& j E- ]+ D - }
, d! x8 X7 i; g1 \ - public DateTime MsgTime { get; set; }1 L- _) ]* K |6 @4 N
- public ArraySegment<byte> MsgContent { get; set; }
, |% @6 h- B- H* D/ H/ u - }
( O3 e7 S2 M! A - ! H# y! S7 t+ _6 ]" ~
& a/ B N K6 n+ [# ~7 C- 5 k+ O% _2 s/ U6 I
! m u0 [6 R1 F/ l( \5 }- /// <summary>
6 H5 K6 t9 e. ~9 i7 B - /// Handler1 的摘要说明
- ~9 ^# z1 o0 v5 Q - /// </summary>9 l8 ^! z2 m4 }0 M7 G2 h
- public class Handler1 : IHttpHandler' i% q. c* t' |% R% g( ^4 L
- {
% |9 z* E' N v9 T - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
5 u% \0 P) {4 O5 W% D5 z - private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池3 B0 H- Y8 I8 g" _0 I; N
- public void ProcessRequest(HttpContext context)% w) b9 O1 V. v
- {8 T' i& w# B+ C* o- v
- //context.Response.ContentType = "text/plain";
: c( Q" t, a! e' J1 E6 Z: G0 _% q - //context.Response.Write("Hello World");' `) ], T5 h0 [9 G
- if (context.IsWebSocketRequest)& {) n4 s* l, T
- {1 L7 Q) t7 a' Z+ Y: b( P
- context.AcceptWebSocketRequest(ProcessChat);9 ?* S7 }' ]3 I2 q3 s2 o E
- } - O. u8 e: H8 m/ ]9 S/ N# f
- }
+ j" ~4 \. C- E. A/ q6 W - 7 X& ~) B) O1 S1 {4 ^8 |7 J
- private async Task ProcessChat(AspNetWebSocketContext context); \2 _; ?9 q# y" @! s: I
- {) h$ f; y5 j+ D T' e% k
- WebSocket socket = context.WebSocket;+ L" H0 j$ h/ v- t; O" |
- string user = context.QueryString["user"].ToString();
2 s1 i" c) j! {& n. ]- B2 ]
' _; U8 d1 X- R6 P! S8 H0 c$ S# I- try; k6 K# V* l5 T. o. U; m$ m; B
- {
. q* q/ K3 `+ a6 k; W- x: P& f - #region 用户添加连接池* t) N e% e0 q G2 K1 X
- //第一次open时,添加到连接池中
0 i7 }) o# O( Z S E% o% d6 M - if (!CONNECT_POOL.ContainsKey(user))
0 w( |9 u/ P. L5 q1 D* a - CONNECT_POOL.Add(user, socket);//不存在,添加
: }: ~. o& P" f3 _( B0 S - else7 H p1 g' R' I
- if (socket != CONNECT_POOL[user])//当前对象不一致,更新
. \- e& u; F) G - CONNECT_POOL[user] = socket;& I7 E. H# k' h' ]# d! q4 s: ^) c
- #endregion; `5 P! I' |9 z" }
- * m$ C% i- E/ n2 A, S X
- #region 离线消息处理+ ?3 k+ t G, L( T2 d( I8 Z
- if (MESSAGE_POOL.ContainsKey(user))4 D$ o( b& a- D5 [1 ^8 B8 j
- {
) k7 l/ B6 t6 X; l, E& [ - List<MessageInfo> msgs = MESSAGE_POOL[user];! j; i( K4 y6 K) p7 @' g
- foreach (MessageInfo item in msgs)
5 {. ^8 z& F0 t5 d - {
( A9 p0 |' Q- G4 B* F - await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);
( S2 ~* B2 F% V' c - }' j; s9 i0 z2 x$ H5 \2 g
- MESSAGE_POOL.Remove(user);//移除离线消息6 v7 e8 c0 F$ I2 u5 P, T
- }& D$ y( C. L; v. a) E) b
- #endregion
% ~$ s% V6 t. x1 J1 D% M5 }: ] - 1 a& a$ c( w m$ u3 P L2 c/ [
- string descUser = string.Empty;//目的用户
$ S5 `0 T8 i# W - while (true)0 R4 x. G' {: c+ k. ~2 w
- {
0 V6 O9 N8 b( Q# Z, u4 X - if (socket.State == WebSocketState.Open)
3 B3 d* @8 \4 w' a9 q: l - {
! m3 {8 A8 G% p - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
2 g% Z8 ]$ m* @" t3 Y) x: c - WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);8 U6 n, @# x. z4 G/ I
% u3 W$ v8 h5 P1 E- #region 消息处理(字符截取、消息转发). E2 m& u% I% |+ K, t
- try
7 a" j5 l! b5 ` - {0 ]" z# s: u% e0 Y7 f- a9 r7 w
- #region 关闭Socket处理,删除连接池
! L# m Q" |5 L) C- V$ V - if (socket.State != WebSocketState.Open)//连接关闭
9 K6 Z+ {$ Z0 Y! I9 g( y: M - { b+ X' a$ x1 K6 R4 @+ d" @- N
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池( U8 [0 b/ A9 [; i8 w- Y
- break;
" K* g+ B# |% s9 y, l3 U/ }+ v - }* l! X4 i; w" w" O/ a* u
- #endregion% d1 K- H6 v3 x; |- G$ W. s
& [% T$ V" ]6 w# h/ \- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息
7 b. o2 b+ ?& @" y' i4 z - string[] msgList = userMsg.Split('|');6 A; i5 k( ~: F0 X4 U! I u3 _( j
- if (msgList.Length == 2)
1 E, ^3 k1 a0 _% n( _/ j - {
) X8 s* [5 j' x: P) U. c - if (msgList[0].Trim().Length > 0)
* E: K+ {4 i7 d) _" Y0 h - descUser = msgList[0].Trim();//记录消息目的用户1 }. {) R, T- ]. F
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));( Q, _- h3 X% X; ^- V
- }/ O9 ` _8 ?* r; ?3 t
- else: y/ T% L( h9 U* c
- buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));- H3 X- k4 t' S: D
- 2 R& G$ o8 @9 c( s4 z/ z
- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
7 }) v8 S$ Z7 `. \$ n/ ] - {
" y Q) h% I4 U6 S: ]4 \ - WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
6 N$ f! q+ X5 A$ M) M9 B5 O' B - if (destSocket != null && destSocket.State == WebSocketState.Open)4 e2 E9 |; e$ q( {
- await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);5 `8 e$ l; I: q
- }$ i3 N+ k2 {! a! G! }- `- S0 g9 Z5 Y
- else
1 S5 n& @2 o: d- T; \0 A* Y - {
3 k" ~! T6 U! r- F( E x" a - Task.Run(() =>- K4 i5 t! Z! E& w* N3 |# `6 m2 X
- {
9 l' l n9 [1 w" c4 F- {$ U; Z& I - if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
/ S6 `% ?! {# g$ h' Q - MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
$ n3 J; j W1 M# L: ~. h, V$ v - MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
( E& E P1 S! u# |$ r0 \1 p - });
2 `; N3 i, ?/ c; _ - }. A! Z* ^# v! g8 o: `1 \, V
- } a/ Y$ P* V! e8 B
- catch (Exception exs)
, B5 T3 F) ~. e2 i# |0 A- A - {
\" P: c+ L7 A - //消息转发异常处理,本次消息忽略 继续监听接下来的消息! o2 {% P2 h( g/ M
- }/ ^" [" F) `! l$ y
- #endregion K/ s6 \# _ Y- N
- }5 U$ e3 G) [+ [) o
- else! f" ?* |! v% j! o
- {9 a0 c! D% _" g" s4 C* |6 e
- break;3 R Q. t, Z6 T8 F2 E3 W# b2 I
- }8 a2 k! g4 h, f' M4 P! ^
- }//while end# _ {- u. W0 u+ E6 P' C _8 L
- }
& ?2 W) b0 m1 z - catch (Exception ex)' M5 |4 W, d& u( T% [) N S( ?
- {
' i% r7 ~5 x8 m- [, ^$ U) u* A2 V - //整体异常处理
' C) [! m& |! G ]4 l1 G - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);2 v; O! m8 L$ Z7 H: ~
- }
) [5 t2 J# U. x - }
9 Z* e: E9 R8 T
( D0 t s" p9 ?0 x: G# j% D+ V. }
4 P) u, r7 p- K8 E- public bool IsReusable9 S; e2 [6 D# T% f+ R- t2 @/ C
- { e; |5 i( p3 O9 ?6 Y
- get
8 e* e* n) U q% u0 ] - {
' z3 M( o, N" K2 X& A9 t) r - return false;
8 t7 c: u' ]3 E. z E4 R p4 M - }2 i2 W p, C* s- d7 n9 w: |4 q
- }5 Z% X$ _6 M4 o7 a4 w2 S) O- K
- }
0 f1 L$ H \1 r - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
0 Y8 S, h* u5 u" z
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |