写在开始

上面一篇写了一篇使用WebSocket做客户端,然后服务端是socke代码实现的。传送门:webSocket和Socket实现聊天群发

本来我是打算写到一章上的,毕竟实现的都是一样的功能,后来想了想就没写在一起,主要是两个方面,

一个原因是这是另一种实现服务方式,放在一起看着有点乱。单独写也方便查阅。二是写是分开写的回家晚上写一点,不能直接在原文上写,就重新起来一个草稿,但是写完就感觉有点懒,不想整合到一块了。嘿嘿,,,

所以对开头说的不明白的同学可以先看一下前面的东西。看一下基础,事半功倍哦。

这一篇不做功能的更改,既然我们使用了WebSocket为什么不使用到底哪,我不喜欢socket的里面出现的打包请求连接数据处理和发送数据处理。可以没有问题啊。那你继续往下看吧。

首先WebSocket服务器这篇我们还是实现的6个功能:

  • 单聊:可以指定人进行聊天。
  • 群发:这个的意思就是当前服务器内的所有人包含自己,这个就跟一个推送效果一样。
  • 开启连接(客户端):通知除自己以外的所有用户
  • 关闭连接(客户端):通知除自己以外的所有用户
  • 群组A:实现一个群组名字为A
  • 群组B:实现一个群组名字为B

技术点

前端写法都是一样的我就不做过多的叙述了,这里只要是针对socket协议的方法进行修改成WebSocket形式。

首先我这次是把服务写成了一般处理程序进行挂载的。(有些有强迫症的小伙伴想改访问路由路径可以参考一下:mvc中路由的映射和实现IHttpHandler挂载

我在本示例就是把放在model下的一个一般处理程序,改写成了socket路径.

原来访问是:http“//http://localhost:端口号/文件夹位置/SocketServer.ashx

改完之后是:http“//http://localhost:端口号/socket/SocketServer.ashx

在实际项目中可以不暴露文件的真是路径位置,还是有点用处的。

不得不说WebSocket确实不错,比如接受发送数据解析方法都给封装好了。

接受方式

既然使用WebSocket做协议当然接受就不用用socket而是使用WebSocket啦。通过在接受到请求后获取上下文中的WebSocket。

            //创建新WebSocket实例
WebSocket myClientSocket = context.WebSocket;
  string userId = context.QueryString["userId"];

在这里我们有一点变化就是socke用户是通过socket随机获取的,这里我修改成了页面传输。前台代码:

 var userId = parseInt(Math.random() * (999999 - 100000 + 1) + 100000, 10);
console.log(userId)
ws = new WebSocket('ws://' + window.location.hostname + ':' + window.location.port + '/socket?userId=' + userId);

判读在线方式

WebSocket有单独的状态来进行在线的判断,不用我们自己写判断处理还是比较好的。

                            #region 关闭Socket处理,删除连接池
if (myClientSocket.State != WebSocketState.Open)//连接关闭
{
if (ListUser.ContainsKey(userId)) ListUser.Remove(userId);//删除连接池
break;
}
#endregion

接受数据

WebSocket也没有辜负我们的期望,接受数据的处理也不需要我们处理的,使用ReceiveAsync方法可以得到消息字节,我们只需要定义一个字节数组段用来接受即可,例如:

                        ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[]);//定义字节数组
WebSocketReceiveResult result = await myClientSocket.ReceiveAsync(buffer, CancellationToken.None);//获得字节
  string userMsg = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);//发送过来的消息

是不是感觉特别的方便,没有了那些乱七八糟的处理了。看着还是挺舒心的。

发送数据

既然接受数据都有单独的方法封装,发送消息没有道理没有的,是的发送使用SendAsync方法,使用形式和ReceiveAsync类似,首先定义一个字节数组段用来存放内容,例如:

                        ArraySegment<byte> buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes($"用户({userIdA}=>{userIdB}):{msg}"));
socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);

这样子就是一个发送过程,先把要发送的字符串转换成字节数组段,然后把这个数组段使用SendAsync发送出去就可以了。

注:在上面的两个方法中我们都看到了ArraySegment这个东西,他到底是个什么哪,他是一个命名在System命名空间下的一个结构体。类似与Array数组但是他又不是数组,为什么这么说,因为他可以接受数组段,他可以只保存内容中的一部分而不是全部。就像别人说的小抽屉一样。我是把他理解成先把他放到这里当作数据缓存区,等真实发送的时候进行发送数据。WebSocketMessageType是一个枚举类型,通过F12可以看到:

    // 摘要:
// 指示消息类型:
public enum WebSocketMessageType
{
//
// 摘要:
// 该消息是明文形式。
Text = ,
//
// 摘要:
// 消息采用二进制格式。
Binary = ,
//
// 摘要:
// 因为收到关闭的消息,接受已完成。
Close =
}

敬上代码

入口函数

一般处理程序中判断只接受WebSocket协议连接进入的运行:

            if (context.IsWebSocketRequest)
{
context.AcceptWebSocketRequest(Accept);
}
else
{ }

消息处理

下面就是同意连接后的主要方法,类似上一篇写的ReceiveMessage方法(接受消息),这里的处理存在一些改动,所以我就把所有代码贴上来了。

 #region 处理客户端连接请求
/// <summary>
/// 处理客户端连接请求
/// </summary>
/// <param name="result"></param>
private async Task Accept(AspNetWebSocketContext context)
{
//创建新WebSocket实例
WebSocket myClientSocket = context.WebSocket;
string userId = context.QueryString["userId"]; try
{ string descUser = string.Empty;//目的用户
while (true)
{
if (myClientSocket.State == WebSocketState.Open)
{
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[]);
WebSocketReceiveResult result = await myClientSocket.ReceiveAsync(buffer, CancellationToken.None); #region 消息处理(字符截取、消息转发)
try
{
#region 关闭Socket处理,删除连接池
if (myClientSocket.State != WebSocketState.Open)//连接关闭
{ if (ListUser.ContainsKey(userId))
{
//退出
SignOut(userId);
ListUser.Remove(userId);//删除连接池
Debug.WriteLine("当前退出用户:" + userId);
}
break;
}
#endregion
string userMsg = Encoding.UTF8.GetString(buffer.Array, , result.Count);//发送过来的消息
string[] resultList = userMsg.Split(',');
if (resultList[] == "login")
{
//登录
Login(userId);
#region 用户添加连接池
//第一次open时,添加到连接池中
if (!ListUser.ContainsKey(userId))
ListUser.Add(userId, myClientSocket);//不存在,添加
else
if (myClientSocket != ListUser[userId])//当前对象不一致,更新
ListUser[userId] = myClientSocket;
#endregion
Debug.WriteLine("当前登录用户:" + userId);
}
else if (resultList[] == "all")
{
//群发所有用户
GroupChat(userId, resultList[]);
}
else if (resultList[] == "groupA")
{
//群组发送
GroupChatA("groupA", userId, resultList[]);
}
else if (resultList[] == "groupB")
{
//群组发送
GroupChatA("groupB", userId, resultList[]);
}
else
{
//单聊
SingleChat(userId, resultList[], resultList[]);
} }
catch (Exception exs)
{
//消息转发异常处理,本次消息忽略 继续监听接下来的消息
}
#endregion
}
else
{
break;
}
}//while end
}
catch (Exception ex)
{
Console.WriteLine("Error : " + ex.ToString());
}
}
#endregion

单聊实现

这里我就不把写的所有单聊,群里,实现群组方法贴上来了,实现的思路还是和以前一样,只是写法不同,我就写一个单聊作为代表示例贴上来。想看全部在下面下载源码就好了。

 #region 单聊
public void SingleChat(string userIdA, string userIdB, string msg)
{
WebSocket socket = ListUser[userIdB];
if (socket != null)
{
if (socket != null && socket.State == WebSocketState.Open)
{
ArraySegment<byte> buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes($"用户({userIdA}=>{userIdB}):{msg}"));
socket.SendAsync(buffer, WebSocketMessageType.Binary, true, CancellationToken.None);
}
} }
#endregion

传送门:

基础版本实现简单的websocket:实现服务端webSocket连接通讯

完善websocket实现聊天示例:WebSocket和Socket实现聊天群发

最后在送上github源码:https://github.com/Yanbigfeng/WebSocketToSocket

【WebSocket No.3】使用WebSocket协议来做服务器的更多相关文章

  1. 开源的C#实现WebSocket协议客户端和服务器websocket-sharp组件解析

    很久没有写博客了(至少自己感觉很长时间没有写了),没办法啊,楼主也是需要生活的人啊,这段一直都在找工作什么的.(整天催我代码的人,还望多多谅解啊,我会坚持写我们的项目的,还是需要相信我的,毕竟这是一个 ...

  2. C#实现WebSocket协议客户端和服务器websocket sharp组件实例解析

    看到这篇文章的题目,估计很多人都会问,这个组件是不是有些显的无聊了,说到web通信,很多人都会想到ASP.NET SignalR,或者Nodejs等等,实现web的网络实时通讯.有关于web实时通信的 ...

  3. websocket --- 05 . http与websocket

    一.http协议 1.基于 TCP 协议 2.一次请求 一次响应 断开 3.客户端永远处于主动状态 4.服务器永远处于被动状态 5.Http无状态 - 在服务器不保存客户端的信息 6.服务器无法主动找 ...

  4. WebSocket实践——Java实现WebSocket的两种方式

    什么是 WebSocket? 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信 ...

  5. WebSocket 实战之——【WebSocket 原理】

    一.WebSocket是什么? HTML5出的东西(协议),也就是说HTTP协议没有变化,或者说没关系,但HTTP是不支持持久连接的(长连接,循环连接的不算). 首先HTTP有1.1和1.0之说,也就 ...

  6. Spring WebSocket初探2 (Spring WebSocket入门教程)<转>

    See more: Spring WebSocket reference整个例子属于WiseMenuFrameWork的一部分,可以将整个项目Clone下来,如果朋友们有需求,我可以整理一个独立的de ...

  7. WebSocket(二)-WebSocket、Socket、TCP、HTTP区别

    原文地址:Socket 与 WebSocket 1. 概述 WebSocket 是为了满足基于 Web 的日益增长的实时通信需求而产生的.在传统的 Web 中,要实现实时通信,通用的方式是采用 HTT ...

  8. websocket之二:WebSocket编程入门

    一.WebSocket客户端 websocket允许通过JavaScript建立与远程服务器的连接,从而实现客户端与服务器间双向的通信.在websocket中有两个方法: 1.send() 向远程服务 ...

  9. 从日常开发说起,浅谈HTTP协议是做什么的。

    引言 HTTP协议作为Web开发的基础一直被大多数人所熟知,不过相信有很多人只知其一不知其二.比如咱们经常用到的session会话机制是如何实现的,可能很多人都说不出来吧.其实session会话就是H ...

随机推荐

  1. 分析Ajax抓取今日头条街拍美图

    spider.py # -*- coding:utf-8 -*- from urllib import urlencode import requests from requests.exceptio ...

  2. win32控制台程序 宽字符与短字符转化

    由于vs各版本之间存在字符设置不兼容问题,特总结char与tchar的互相转换函数,如下,在之后的工程中可以使用. void TcharToChar(const TCHAR * tchar, char ...

  3. DB2日常维护常用命令

    1.检查是否有僵尸进程 ps -emo THREAD | grep -i Z | grep -i 实例名 2.处理死锁  --第一步:查看所有死锁  db2 get snapshot for lock ...

  4. 第一课:Python入门(笔记)

    一.变量 1.什么是变量 #变量即变化的量,核心是“变”与“量”二字,变即变化,量即衡量状态. 2.为什么要有变量 #程序执行的本质就是一系列状态的变化,变是程序执行的直接体现,所以我们需要有一种机制 ...

  5. git了解-使用笔记

    1.Git的由来与设计理念 Git是linux之父Linus Torvalds开发的,是一款最先进的项目版本控制系统. Git的由来有一个小故事,传闻起初Linux社区工作者都是通过邮件的,发送给li ...

  6. 背水一战 Windows 10 (109) - 通知(Tile): 按计划显示 tile 通知, 轮询服务端以更新 tile 通知

    [源码下载] 背水一战 Windows 10 (109) - 通知(Tile): 按计划显示 tile 通知, 轮询服务端以更新 tile 通知 作者:webabcd 介绍背水一战 Windows 1 ...

  7. Senparc.Weixin.TenPay 正式发布

    微信支付刚出来的时候,和公众号的绑定关系很深(甚至旧版本使用的就是公众号的appId),随着微信生态的逐步丰富,微信支付越来越成为一个独立的平台,同时服务于公众号.小程序.开放平台.企业号/企业微信等 ...

  8. [转]语言模型训练工具SRILM

    SRILM是一个建立和使用统计语言模型的开源工具包,从1995年开始由SRI 口语技术与研究实验室(SRI Speech Technology and Research Laboratory)开发,现 ...

  9. 每天学点SpringCloud(十):SpringCloud监控

    今天我们来学习一下actuator这个组件,它不是SpringCloud之后才有的,而是SpringBoot的一个starter,Spring Boot Actuator.我们使用SpringClou ...

  10. rabbitmq系统学习(二)

    Rabbitmq高级整合应用 RabbitMq整合Spring AMQP实战 RabbitAdmin 使用RabbitTemplate的execute方法执行对应操作 rabbitAdmin.decl ...