一封给“X教授”的回信(讨论Socket通信)
转载:http://www.cnblogs.com/tianzhiliang/archive/2011/03/02/1969187.html
前几天“X教授”发Email与我讨论Socket通信方面的问题,主要涉及4个方面内容,现将回信公布出来,希望园友们能积极参与讨论,提出更好的解决方案。
下面是“X教授”的来信:
===========================================================
您好,我看了您写的几篇博文,想请教你几个.net Socket通信方面的问题,这些问题以前一直困扰着我。
1、按照你深入探析C# Socket的文中的说法。
对于Socket的同步操作来说,Socket的RceiveBuffer和SendBuffer没有用处,因我发送时是从应用程序缓存(这里指字节数据)直接拷贝到基础系统发送缓冲区,接收时是从基础系统接收缓冲区拷贝到应用程序的缓存。
Socket本身的接收缓存与发送缓存,是否只与异步Socket操作有关。在异步操作中又分为两种,一种是以BeginXXX系列操作,以BeginSend为例,对这种操作我的理解是,从线程池中取一个线程,把数据拷贝到Socket的自带的SendBuffer中,调用BenginSend的主线程然后立刻返回,该发送线程挂起,由操作系统把SendBuffer中的数据拷贝到基础系统缓冲区,发送完成后,挂起的线程激活,调用EndSend进行相应的操作,释放异步对象等资源。
以上我的理解是否正确。
2、除XXXAsync系列操作外, BeginXXX系统的Socket操作是否也是用的完成端口机制。
3、.net与C/C++写的结构体通信。目前我熟悉的就两种:
第一种是了MarShal类进行结构体的转换操作,但托管与非拖管之间交互时的封送开销,使得其效率不高。
第二种是用流的方式去解析数据包。然后按包结构,一个字段一个字段的去读取。比如比流出读取一个浮点型,binr.ReadSingle();此种效率还可以。接收与解析好几M的数据没有问题。
我想问一下,有没有效率更高的方法。
4、服务器给客户端转发数据,当客户端接收包的地方堵塞(可能是socket.Receive),有没有什么好的方案,让服务器自动丢包。
===========================================================
下面是我的回信:
===========================================================
X教授,您好:
非常抱歉,最近比较忙,耽误给您回复了。对于您提出的几个问题,我只能作浅层次的回答,更深的研究,我们以后慢慢探讨,共同学习。
第一个问题:
你的理解是正确的,对于同步发送,是直接拷贝发送数据到基础系统的发送缓冲区,与Socket本身的Buffer无关。对于异步发送,是将Socket自带的Buffer空间内的所有数据,拷贝到基础系统发送缓冲区,并立即返回。
在实际开发中,个人觉得采用异步接受、同步发送。也许你会感到很惊讶,很明显,异步操作明显比同步操作效率高很多,为什么发送要采用同步呢?不知道你在开发过程中有没有遇到过“现在已经正在使用此 SocketAsyncEventArgs 实例进行异步套接字操作”错误,这个错误是由于SAEA对象在一个时刻中只能处于StartAccept、StartReceive、StartSend状态中的一种,试想,当Socket服务器处于高压力情形下,一条Socket连接在很短的时间内要发送大量数据,当Socket处于StartSend状态下尚未触发回调函数时,又一次调用此Socket的StartSend方法,便会抛出该异常。这也有改进方案:记录Socket的当前状态,并存储在Socket的UserToken对象下,当要执行StartSend时,判断状态。不过这样效率会很慢,远远低于同步发送的效率,当高并发时,还要用大量的锁机制来维护线程的同步,得不偿失。不知道你有没有更好的改进方案,如果有,请告知我,不胜感激。
第二个问题:
BeginXXX系统的Socket操作采用的是完成端口机制,在初始化SAEA对象时,会为SAEA对象设定回调函数。
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
第三个问题:
建议使用流的方式解析数据包。
在解析数据包的过程中,不知道您有没有遇到过粘包的现象,我觉得对粘包的处理是影响解析效率的关键,请参见博文:http://www.cnblogs.com/tianzhiliang/archive/2010/08/31/1813659.html。
第四个问题:
我觉得采用“心跳”是一个不错的解决方案。
“心跳”分为两种,第一种是客户端发起的心跳,第二种是服务端发起的心跳。
客户端发起的心跳:客户端每隔一段时间发送策略消息给Socket服务器,Socket服务器原路返回策略消息,如果客户端在设定时间段内没有收到Socket服务器的返回消息,经重试机制后,判定Socket服务器已Down,关闭连接。
服务端发起的心跳:服务端实时记录每条Socket的IO操作时间,每隔一段时间获取所有Socket列表的快照,扫描每条Socket,如果该Socket的IO操作时间距当前时间已超出设定值,则判定客户端Down,关闭连接。
一封给“X教授”的回信(讨论Socket通信)的更多相关文章
- C#调用C/C++动态库 封送结构体,结构体数组
因为实验室图像处理的算法都是在OpenCV下写的,还有就是导航的算法也是用C++写的,然后界面部分要求在C#下写,所以不管是Socket通信,还是调用OpenCV的DLL模块,都设计到了C#和C++数 ...
- “IT学子成长指导”专栏及文章目录 —贺利坚
迂者专栏关键词 就 业 大一 大二 大三 大四 自学 职 场 专业+兴趣 研究生 硕士 规 划 考 研 大学生活 迷 茫 计算机+专业 基本功 学习方法 编程 基 础 实践 读书 前 途 成 长 社团 ...
- 强哥的分享--如何使用Spring Boot做一个邮件系统
http://springboot.fun/ actuator是单机.集群环境下要使用Spring Boot Admin将各个单机的actuator集成越来 mvn clean package -Dm ...
- (转)我看PhD by 王珢
我看PhD by 王垠 前段时间看了一下这些关于 PhD 的负面信息: 一个专门反对读 PhD 的 BLOG 叫“100 Reasons NOT to Go to Graduate School”(下 ...
- [转]为什么我要用 Node.js? 案例逐一介绍
原文地址:http://blog.jobbole.com/53736/ 介绍 JavaScript 高涨的人气带来了很多变化,以至于如今使用其进行网络开发的形式也变得截然不同了.就如同在浏览器中一样, ...
- iOS:iOS开发非常全的三方库、插件等等
iOS开发非常全的三方库.插件等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自git ...
- 【转】为什么我要用 Node.js? 案例逐一介绍
原文转自:http://blog.jobbole.com/53736/ 介绍 JavaScript 高涨的人气带来了很多变化,以至于如今使用其进行网络开发的形式也变得截然不同了.就如同在浏览器中一样, ...
- Node.js(转) -- 临时来说还看不懂!
转自:http://blog.jobbole.com/53736/ 本文由 伯乐在线 - Lellansin 翻译.未经许可,禁止转载!英文出处:toptal.欢迎加入翻译组. 介绍 JavaScri ...
- CTSC2017总结
这个博客已经弃坑近一年了,自从去年国赛大力卡线进队后这近一年来我的情况从博客一年没更就可见一斑,OI水平原(zhi)地(xian)踏(fu)步(chong),炉石和双升的姿势水平倒是提高不少. 在经历 ...
随机推荐
- oracle时间模型
Oracle在9i或者早期的版本,对于性能优化方面,主要采用命中率模型,后面的版本,也保留着命中率模型,比如在awr报告中,Instance Efficiency Percentages (Targe ...
- 数据库sql整体整理
create database 数据库 /* 数据库的服务.数据库文件. */ --修改表添加列 create table biao ( name ) ) ) --往表里增加一列 alter tabl ...
- 使用表达式避免拼接SQL语句
在SQL语句编写过程中,无论在存储过程中还是在程序中,有时为了使语句兼容全部情况与某字段的特殊情况,不得不拼接SQL字串 如下表 商品ID 类别ID 1 1 2 1 3 2 4 3 5 3 如果我们要 ...
- Android4.0 -- UI控件之 Menu 菜单的的使用(二)
上一讲我们讲解了android中在代码或者xml文件中定义菜单,这一讲我们继续来讲解一下定义菜单的其他方式:创建上下文的菜单.查看API文档 Menus :Creating Contextual Me ...
- Never use GetDate() when comparing date timesoffsets, use SYSDATETIMEOFFSET()
-- my current uk time is 2014-01-09 10:43:00 +0 ) = '2014-01-09 18:43:00 +08:00'; ) = '2014-01-09 02 ...
- JavaScript---网络编程(3)-Object、String、Array对象和prototype属性
本节学习JavaScript的对象和方法(函数)~ Object 对象 提供所有 JScript 对象通用的功能. obj = new Object([value]) 参数 obj 必选项.要赋值为 ...
- How to compile pycrypto 2.4.1 (python 3.2.2 for Windows 7 x64)
How to compile pycrypto 2.4.1 (python 3.2.2 for Windows 7 x64) Nov 10 Posted by alesk This note is a ...
- PHP如何让apache支持.htaccess 解决Internal Server Error The server …错误
TP框架 打开 www.newtp.com/index.php/Home/Index/abc出现 如下错误: Internal Server Error The server encountered ...
- Java 8 新特性概述
Oracle 在 2014 年 3 月发布了 Java 8 正式版,该版本是一个有重大改变的版本,对 JAVA 带来了诸多新特性.其中主要的新特性涵盖:函数式接口.Lambda 表达式.集合的流式操作 ...
- SpringMVC接收页面表单参数(转)
作者:CN.programmer.Luxh 和java相关 一个普通的表单. 表单的代码如下: <%@ page language="java" contentType=&q ...