cncml手绘网
标题: 在IIS上搭建WebSocket服务器(二) [打印本页]
作者: admin 时间: 2018-11-7 00:43
标题: 在IIS上搭建WebSocket服务器(二)
服务器端代码编写
1.新建一个ASP.net Web MVC5项目
& b+ j+ F2 C! T' Q+ N- M* f2.新建一个“一般处理程序”
3.Handler1.ashx代码如下:
- using System;8 j1 A+ Q( L- a/ B, }" P
- using System.Collections.Generic;; f) c6 x$ k! z2 n4 T0 ~* j
- using System.Linq;( b( }% `9 R; R# c$ J0 x7 H8 K
- using System.Net.WebSockets;
" [4 f$ X" i) H) \4 D - using System.Text;7 h( M" t7 [5 n& Q! G
- using System.Threading;3 J2 b+ ]/ t+ R0 C3 ?
- using System.Threading.Tasks;
/ D+ y, h$ [1 _" b, o, W, s2 @6 d - using System.Web;
3 W8 P, P* i `& R4 l |5 _ - using System.Web.WebSockets;
9 N3 F k9 f3 u: I
% ]! ?6 P$ C1 R" g: S
2 T% k' {% `7 x, A/ f- ]- g- namespace WebApplicationWebsocketHandler
, W* ^+ o+ ]) H7 P; `; @) x0 o - {' z U, }/ o" e) s; \
- /// <summary>
7 Y: h; M# L& b& b5 z4 K8 v - /// 离线消息
; j; ?) b# T7 w7 D - /// </summary>
7 f. H& r$ u7 L* l' t, _$ S - public class MessageInfo# N* `6 e3 W5 A# I! w& c
- {
' O+ B3 |8 Z2 m: ?1 s, d& z, j - public MessageInfo(DateTime _MsgTime, ArraySegment<byte> _MsgContent)- q0 V" B: s4 J6 G3 ~; E
- {
' s$ }0 d% e- x, _' a6 S: F - MsgTime = _MsgTime;
a" J% \- ~9 h2 C: D U - MsgContent = _MsgContent;
2 Z: N7 V3 w v - }
2 i }- A3 l, [: I - public DateTime MsgTime { get; set; }6 z" ?( S9 k- h
- public ArraySegment<byte> MsgContent { get; set; }6 M! e/ f/ a4 j2 S+ K3 Z
- }
5 K' S1 ?! W: O
2 K, r8 O& \/ E! U" a7 s
4 X& o2 H% V. Y: f8 ?1 T
8 L) X+ B9 u V9 N! U& F) T- 3 E# C- o9 M( J6 X$ d0 @4 z
- /// <summary>
& Z. r0 m" ^. M2 W - /// Handler1 的摘要说明7 r) V* q/ G# X& `: \% ~" C9 Y; }. w
- /// </summary>
! r1 }" @' M' A# \ ~) C - public class Handler1 : IHttpHandler
- _% Y8 a5 O/ z" @ - {
( c/ t$ b9 k; {4 Q5 T b - private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池9 W( O1 W# N& v( X8 I- Y) |: {
- private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
& P$ _) Y# f- W6 A3 Z - public void ProcessRequest(HttpContext context)' [2 U5 W/ |; F3 f% ?0 K' k
- {/ R- _* [ u3 y4 ~1 `$ P, a
- //context.Response.ContentType = "text/plain";' B6 D" b: f7 \) {
- //context.Response.Write("Hello World");( x# S `+ \* J8 `' q
- if (context.IsWebSocketRequest)$ y+ F3 ^. q& X
- {/ N: k- l; e) h
- context.AcceptWebSocketRequest(ProcessChat);3 e7 B1 E. M9 X3 f4 N3 h+ m
- }
2 {, P. y* J$ b/ `( m - }
1 S$ R( ]; k0 d/ |; Y1 y) R' m" i
& @5 u. ~. i7 q% N0 d0 p# o1 C- private async Task ProcessChat(AspNetWebSocketContext context)! ~" R/ ~; x2 S
- {5 q4 {# B# T" f0 N. @9 e# N/ F
- WebSocket socket = context.WebSocket;& Z/ t7 ]4 L; j/ u
- string user = context.QueryString["user"].ToString();
1 `* Z# \% H# w0 w1 P4 R
3 \' u' F3 m3 H% R% X3 W5 L- try
X& Y3 B4 @- h Z k7 B - {
1 n c Q- W" M& B4 W$ \ - #region 用户添加连接池
3 c; J. J( d( R! Z! U - //第一次open时,添加到连接池中
% Q1 F# Q, D8 g& E - if (!CONNECT_POOL.ContainsKey(user))/ n- V, U T+ u- s/ H
- CONNECT_POOL.Add(user, socket);//不存在,添加" H8 r) x' d. m9 C& B! h6 \* F
- else
! W Z# |" D5 S - if (socket != CONNECT_POOL[user])//当前对象不一致,更新% e+ V1 ]) v1 {- G
- CONNECT_POOL[user] = socket;8 n9 O+ ?/ U# ^% R
- #endregion
9 F" z. o/ Q" t9 h0 E" k: q0 J V
* F. ^& a+ g; m% x) v- #region 离线消息处理" R' o+ f2 j5 g6 E% [1 O0 g
- if (MESSAGE_POOL.ContainsKey(user))
+ o- N! |% i6 ]( y0 A/ Y Z - {
% o/ ~, W: l: I6 W+ q - List<MessageInfo> msgs = MESSAGE_POOL[user];3 {6 h, Y( h1 E/ ^
- foreach (MessageInfo item in msgs)
% ]3 m. ^3 A0 G z$ X - {# Q8 n% A- l9 L7 P; ?6 R
- await socket.SendAsync(item.MsgContent, WebSocketMessageType.Text, true, CancellationToken.None);( P9 X+ S: |, N, g- h
- }
6 D) [. z Q2 V& @6 @ - MESSAGE_POOL.Remove(user);//移除离线消息5 D4 T7 F5 s& M
- }2 Q' O! S* \+ Y+ Y& X2 T
- #endregion+ r; D$ L5 U; h( [1 x
) ^5 b; J- q7 f+ V; s- string descUser = string.Empty;//目的用户
6 [( ]$ P, Q5 v- v& M- R - while (true)
4 [& a8 T- y+ p - {5 }1 U, h) [! R l1 I
- if (socket.State == WebSocketState.Open)
* {% X8 }' F8 e. X7 a" L - {
" N. |% D& j; j' x! ]4 R - ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);; B- u7 C ^- g
- WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);0 p" c" r$ l3 `, K& }' }+ E
) w# D9 g3 V1 S% Z% p! b4 g* u" o- #region 消息处理(字符截取、消息转发)
( X. m) ?' u. ~4 [- T3 I" s: n9 Y - try4 P2 u X5 v- P+ h
- {
7 B2 H$ {; T5 U, h - #region 关闭Socket处理,删除连接池- D9 I$ n2 z6 t% j1 l
- if (socket.State != WebSocketState.Open)//连接关闭
' q) a3 k8 q; F( x6 \0 { - {
4 d0 D" @! m0 e) K3 m- @$ V& ^& x - if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);//删除连接池
2 N, L, {5 _* d - break;# N* ?+ Z( N4 |
- }
e$ K( G8 N# S+ Y - #endregion% t+ x+ X- m) Y9 J
- $ C9 ?, y2 w4 ^* e
- string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息5 K6 G( w ?. _1 \
- string[] msgList = userMsg.Split('|');
4 U# L& w. N6 @ Y. `' V: }" k - if (msgList.Length == 2)+ x$ x9 ]! Z' t4 I; H1 E7 w
- {
( r# j/ q/ v; n% ?8 m8 M- n - if (msgList[0].Trim().Length > 0)
( a2 T- o+ s4 P - descUser = msgList[0].Trim();//记录消息目的用户
: x6 h) e/ l; B - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgList[1]));/ X7 Q$ B: B& Q: a1 M8 m6 X% Q* R
- }* D( Y1 Y; _2 M* @7 A% `& [
- else
4 v5 w) L/ J* y6 J* }* J8 A - buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userMsg));
/ X2 \5 |$ i, r, _ - % f7 x1 X% `( d! v% W; @
- if (CONNECT_POOL.ContainsKey(descUser))//判断客户端是否在线
v' `. q3 T, a+ v' f! ^# A - {7 \$ O# [3 B( E2 t2 c, q
- WebSocket destSocket = CONNECT_POOL[descUser];//目的客户端
' Y9 R4 d% t) ~9 c - if (destSocket != null && destSocket.State == WebSocketState.Open)
0 h8 B7 f& ?! r& _1 n" e - await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
+ H) s" `2 Z" i; V - }
1 P! d8 {8 u( U" Q" d - else
# Y& _/ J5 M- t) S - {/ B* M1 T& \$ \' ?. r; q4 j
- Task.Run(() =>
9 ^% [( K. L) n - {
$ [/ m, T4 u( L- n7 B1 @4 z/ y - if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
0 m& F" B0 Q0 m. W% J - MESSAGE_POOL.Add(descUser, new List<MessageInfo>());. Z" |- B! Y6 c1 X; T
- MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
8 b; P& J3 u: f. | - });8 }% N" C' @. r& I/ H8 W8 {( D
- }
3 j/ E8 h" c5 l1 Q; G - }
& Y+ g% W# p, ~. ? - catch (Exception exs)
! i1 B: L8 Q/ k# E. p' Z - {) d* `+ X( z4 C/ R% t$ S+ Q6 v
- //消息转发异常处理,本次消息忽略 继续监听接下来的消息# z+ ?: n6 t/ D# X, b
- }
3 y0 f5 |: ]1 D1 Y9 i - #endregion
- h6 f" o! X& q5 L) K, @ - }
! B& R0 }0 c; [# m9 Y' ` - else
/ X' v# P1 }- }. q/ I# r3 A - {
: X' W- Y3 n$ p( n - break;' J; ~- O9 h% M9 m- q- S. v- B
- }
9 b- ^. E2 M" i$ E& Y - }//while end
: K! Y: a8 h7 T - }0 s& ]# l: \& K3 g+ i
- catch (Exception ex)8 b9 b. ~- e& u) l
- {6 F! a6 |2 k' K3 T9 v* U9 T# q8 w
- //整体异常处理) D, a' \4 A$ L& B6 L/ L
- if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);! d. g8 z7 V5 ~, g9 s' t
- }) B n! l2 |7 J$ ~/ Y, w
- }5 r) h1 r; C) U2 Q8 B; ]
: E% ]3 W* _7 e5 |/ {" P4 Q/ r# K- $ _; u# i& N) U# D$ y
- public bool IsReusable
+ L) S& E7 _* @. z4 o: Y6 L4 L - {
! l: M- `8 R, H; L8 ?# f - get
# O8 I* j2 s* k& X - {% X! w b1 m+ n- Z5 [/ l; U- m
- return false;; y" B9 V; L$ G( w, L
- }
, e# ?( P& D9 y - }
. N2 I" k9 b3 w% \ - }
( w4 D* T4 V Q0 r# G - }
复制代码4.运行看是否报错,若没错将我们的服务器网站发布到IIS(支持WebSocket的IIS上,win7的系统时不可以的)上
点击“生成”->"发布........",以文件系统的方式发布,目标位置为我们创建的IIS网站对应的物理路径
8 H ?8 r* [: d" j8 `" [0 S
| 欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |