在前面《字节和字符,对信息进行编码》,《Socket=>流,TCP连接,TCP可靠性概述》一系列的随笔中我们已经表述了相应的理论知识,现在可以动手实现一个自己的应用程序协议。

将数据转换成在线路上传输的字节序列只完成了一半的工作,在接收端还必须将接受到的字节序列还原成原始信息。如果以流作为传输的形式,那么首先面临的问题就是在接收端如何确定这是一条消息,换句话说就是如何定位一条消息的开始和结束。值得注意的是,这个工作应该是在应用程序协议这一层来完成而不是在TCP这一层来完成,应用程序协议必须指定消息的接受者如何确定何时消息已完整接收。

TCP协议中没有消息边界的概念,这会让我们在解析信息的时候产生一些问题。
如果接收者试图从套接字中读取比消息本身更多的字节,将可能发生以下两种情况:
1.如果信道中没有其他消息,接收者将阻塞等待,同时无法处理接收到的消息;如果发送者也在等待接收端的响应消息,那么就会造成“死锁”
2.如果信道中还有其他消息,则接收者会将后一条的消息的一部分甚至全部读取到第一条消息中,这将会产生一些“协议错误”
因此,在时候流TCP套接字的时候,成帧就是一个非常重要的考虑因素。
对于成帧,主要有两个技术能使接收者能够准确地找到消息的结束位置:
1.消息的结束由一个特殊的标记指明,比如把一个特殊的字节序列0001等显式添加到一个消息的结束位置。这里的限制就在于传输的内容中不能包含和该特殊字节序列中一样的字符。就像HTML中<和>符号不能直接包含在输出中,这时需要转义。
2.显式的告知长度。
在变长字段或消息前面附加一个固定的字段,用来表示该字段或者消息中包含了多少个字节。
我们来写一个网络上常见的投票来作为例子:
这个例子包含了两种类型的请求,一种是“查询”的请求,也就是查询当前的候选人获得的选票情况。
第二种是“投票”请求,服务器保存此次投票信息,并返回投完票后该候选人获得的结果。
在实现一个协议的时候,定义一个专门的类来存放消息中所包含的信息是大有裨益的。类提供了给我们封装的能力,通过属性来公开类中的可变字段,也可以维护一些不变的字段。

我在这里采用的发送消息大小的方式来确定一条完整的消息。

项目结构和功能说明如下:

IFramer接口的定义:
namespaceVoteForMyProtocol{publicinterfaceIFramer    {voidframeMsg(byte[] message);byte[] nextMsg();    }}

基于长度成帧的实现

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Net.Sockets;usingSystem.IO;namespaceVoteForMyProtocol{publicclassLengthFramer : IFramer {publicstaticreadonlyintMAXMESSAGELENGTH=65535;        Socket s=null;publicLengthFramer(Socket s)        {this.s=s;        }//把消息成帧并发送publicvoidframeMsg(byte[] message){if(message.Length>MAXMESSAGELENGTH) {thrownewIOException ("message too long");            }inttotalSent=0;intdataLeft=message.Length;//剩余的消息intthisTimeSent;//保存消息长度byte[] datasize=newbyte[4];            datasize=BitConverter.GetBytes(message.Length);//将消息长度发送出去thisTimeSent=s.Send(datasize);//发送消息剩余的部分while(totalSent<message.Length)            {                thisTimeSent=s.Send(message, totalSent, dataLeft, SocketFlags.None);                totalSent+=thisTimeSent;                dataLeft-=thisTimeSent;            }        }//按帧来解析消息publicbyte[] nextMsg(){if(s==null)thrownewArgumentNullException("socket null");inttotal=0;//已接收的字节数intrecv;//接收4个字节,得到“消息长度”byte[] datasize=newbyte[4];//如果当前使用的是面向连接的 Socket,则 Receive 方法将读取所有可用的数据,直到达到 size 参数指定的字节数。//如果远程主机使用 Shutdown 方法关闭了 Socket 连接,并且所有可用数据均已收到,则 Receive 方法将立即完成并返回零字节。recv=s.Receive(datasize,0,4,0);if(recv<4)returnnull;intsize=BitConverter.ToInt32(datasize,0);//按消息长度接收数据intdataleft=size;//容器装满了就证明收集到了一条完整的消息。byte[] data=newbyte[size];//直到容器填满再返回while(total<size)            {                recv=s.Receive(data, total, dataleft,0);                total+=recv;                dataleft-=recv;if(dataleft==0)                {break;                }            }returndata;        }

    }}

转载于:https://www.cnblogs.com/lwzz/archive/2011/08/11/2135604.html

用TCP/IP实现自己简单的应用程序协议:成帧器部分相关推荐

  1. php把语音转成帧,[转载]用TCP/IP实现自己简单的应用程序协议:成帧器部分

    在前面<字节和字符,对信息进行编码>,<Socket=>流,TCP连接,TCP可靠性概述>一系列的随笔中我们已经表述了相应的理论知识,现在可以动手实现一个自己的应用程序协 ...

  2. TCP/IP四层模型简单介绍

    OSI七层参考模型 OSI(Open System Interconnection 开放系统互联)参考模型,是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系. OSI分为七层 ...

  3. TCP/IP模型的简单解释

    TCP/IP模型是互联网的基础.想要理解互联网,就必须理解这个模型.但是,它不好懂,我就从来没有搞懂过. 前几天,BetterExplained上有一篇文章,很通俗地解释了这个模型.我读后有一种恍然大 ...

  4. 计算机网络复习总结:什么是OSI7层模型、5层模型、TCP/IP 4层模型,各层协议导航

    个人总结整理相关计算机网络知识点,出发点是各类问题以及比较重要的部分. 一.OSI 七层模型 OSI 的七层模型从上到下依次是: 应用层 表示层 会话层 运输层 网络层 数据链路层 物理层 七层模型开 ...

  5. 【转】:TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute

    TCP/IP详解学习笔记(4)-ICMP协议,ping和Traceroute 分类:            TCP/IP详解学习笔记计算机网络2006-04-20 18:147970人阅读评论(1)收 ...

  6. 网络原理 | TCP/IP中的连接管理机制 重要协议与核心机制

    应用层.传输层.网络层.数据链路层.物理层 一.应用层协议 应用层 是程序猿最最经常打交道的一层 其他四层,都是操作系统.驱动.硬件,实现好了的,咱们不需要管 (除非你是系统工程师,驱动开发工程师-- ...

  7. 读书笔记五:TCP/IP详解之RARP逆地址解析协议

    RARP的介绍 具有本地磁盘的系统引导时,一般是从磁盘上的配置文件中读取IP地址,而对于无盘机,则需要用RARP来获取IP地址. 已知mac地址,获取该物理地址的ip地址.无盘系统获取ip地址就是采用 ...

  8. TCP/IP和OSI4层、7层协议介绍

    1.TCP/IP全称:Transmission Control Protocol / Internet Protocol 中文翻译:传输控制协议 / 互联网协议 2.OSI4层.7层模型: 转载于:h ...

  9. EPSON机器人建立TCP/IP通讯的简单demo

    以下为我近期研究EPSON机器人通讯的经验总结,主要实现机械手接收相机发送过来的数据,从而达到对应的位置,及其简单demo. 欢迎加入知识星球[3D视觉工坊],进行交流学习.

  10. 简单叙述tcp/ip的工作原理和主要的协议_802.11协议精读3:CSMA/CD与CSMA/CA

    序言 在前一份文档中,我们详细记录了有关802.11中DCF模式以及其核心CSMA/CA的一些内容与细节.对比无线网络,有线网络的集线器和中继器设计中,采用了CSMA/CD技术.该技术早期是用来解决有 ...

最新文章

  1. 【SAP技术】SAP不能修改一个已经分配给交货单的HU
  2. hadoop的伪分布安装(低版本)
  3. 光端机的作用有哪些?
  4. 二十四点游戏python_[求助]关于二十四点游戏python
  5. 社群广场程序公众号版本程序源码-支持群采集
  6. php自动打印小票_php操作 cookie
  7. Android系统联系人全特效实现(上),分组导航和挤压动画
  8. 梦幻群侠传5帮派修炼_梦幻群侠传5唯美版
  9. Leetcode-403-青蛙过河(DFS+备忘录)
  10. Max and Min---递归
  11. 模板引擎-1-基础概念和是使用小案例
  12. NOIP2013Day1
  13. 海量数据(面向面试)
  14. Android攻城狮四大组件之Service
  15. lyx插入图片和表格
  16. 8421码 5421码 2421码 余三码
  17. kmp算法中字符串前后缀公共长度的总结
  18. 路由控制配置filter-policy export命令解析
  19. oracle 倒库命令
  20. Python实现抓狐狸小游戏

热门文章

  1. C++中继承和派生详解(公有、私有、保护继承的区别)
  2. 初始化请求例子_当一个http请求来临时,SpringMVC究竟偷偷帮你做了什么?
  3. HarmonyOS 编译系统源码
  4. 龙芯rtc时间关机重启后不能保存问题分析
  5. input type=file与cursor:pointer的兼容性问题
  6. jquer同时选择多个不同的id执行同意操作
  7. C++公有、私有、保护继承的关系
  8. 京沪等地11月房价半年来首涨 平价走量将成主流
  9. 使用 JSONModel
  10. Cocos2d-xJson数据解析(读取和写入)