在前面《字节和字符,对信息进行编码》,《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

{

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

{

recv=s.Receive(data, total, dataleft,0);

total+=recv;

dataleft-=recv;if(dataleft==0)

{break;

}

}returndata;

}

}

}

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

  1. 以太网最小帧长与TCP/IP的联合运用

    以太网最小帧长与TCP/IP的联合运用 @(计算机网络) 在平均往返时延RTT = 20ms的快速以太网上运行TCP/IP协议,假设TCP的最大窗口尺寸是64KB,问此时TCP协议所能支持的最大数据传 ...

  2. 怎么将语音转换成文字?这两种转换方法极其简单

    怎么把语音文件转换成文字呢?大家在日常中可能不会经常使用到语音文件,但是不代表没有,在一些比较重要的会议场合下,我们可能会选择使用录音工具来将会议内容记录下来,防止自己会错过什么重要内容.当我们将录好 ...

  3. 【转载】TCP/IP协议详解

    转载链接,若侵删 https://blog.csdn.net/weixin_44198965/article/details/90083126 为什么会有TCP/IP协议 在世界上各地,各种各样的电脑 ...

  4. php把语音转成帧,视频中提取音频软件 怎样把视频中的音乐提取出来,视频转换成音频方法...

    很多时候下载了一个视频文件,但真正吸引到自己的却是视频中的音乐.甚至有时候并不是想要视频文件,而是想要视频中的声音.那怎样把视频格式转换成音频(WAV,m4a,amr,mp3,ra等)格式呢?一般常见 ...

  5. 【转载】TCP/IP 之 大明王朝邮差

    原文:TCP/IP 之 大明王朝邮差 原创 2016-05-12 刘欣 码农翻身 前言: 本文主要想说一下TCP的知识, 比喻有不恰当之处,敬请包涵. 大明王朝天启四年, 清晨. 天色刚蒙蒙亮,我就赶 ...

  6. 【计算机网络】数据链路层 : 总结 ( 封装成帧 | 流量控制与可靠传输 | 差错控制 | 介质访问控制 | 局域网 | 广域网 | 数据链路层设备 ) ★★★

    文章目录 一.数据链路层 功能 二.封装成帧 ★ 三.流量控制 和 可靠传输 ★★ 1.停止等待协议 ★ 2.后退 N 帧 ( GBN ) 协议 ★ 3.选择重传 ( SR ) 协议 ★ 四.差错控制 ...

  7. 《TCP/IP详解卷1:协议》——第2章:链路层(转载)

    1.引言 从图1-4可以看出,在TCP/IP协议族中,链路层主要有三个目的: (1)为IP模块发送和接收IP数据报: (2)为ARP模块发送ARP请求和接收ARP应答. (3)为RARP发送RARP请 ...

  8. 3.2.1 封装成帧、帧定界、帧同步、透明传输(字符计数法、字符串的首尾填充法、零比特填充的首尾标志法、违规编码法)(转载)

    原文链接:https://blog.csdn.net/weixin_43914604/article/details/104779973 本博客为个人学习.研究或者欣赏用,如有侵权,请与我联系删除,谢 ...

  9. 如何将语音转换成文字?转换方法介绍

    语音转换成文字方简单,只需要借助到转换工具就可以了,转换工具有着强大的转换功能,可以轻松实现你想要的转换,不知道转换方法的话,来看看下面的介绍你就会知道! 转换的具体方法如下: 1:打开语音转文字转换 ...

最新文章

  1. vscode 逗号不换行_在VSCode里面配置Vim正确姿势(细节解析)
  2. neo4j客户端下载
  3. c#将对象序列化为字符串和将字符串反序列化为对象
  4. RHEL7切换Firewall为iptables
  5. 【机器学习】九种顶流回归算法及实例总结
  6. CaSS中lisp命令不可用_小白想要自学南方cass?又苦于不会修改比例尺,这里有一份小白快速上手的测绘神器...
  7. 隔壁大爷都会网络布线啦、搞起来搞起来
  8. 关于 运行root.sh 时出错误Timed out waiting for the CRS stack to start.的解决
  9. Apache Camel 2.16发布–十大亮点
  10. python 某个数是不是在某个范围内_教写一个简单的python小程序(04)
  11. php 比较字符串或文章的相似度
  12. 单处理机系统的进程调度实验_Chcore -- 上交IPADS操作系统银杏书配套Lab实验笔记 - Lab3进程与异常(一)...
  13. DDD(领域驱动设计)系列之二-应用架构
  14. spring 3.0.5+velocity tools 2.0
  15. 客户和顾客是一个意思吗_“啤酒度数”和“啤酒酒精度”一个意思吗?
  16. 安卓Android资源链接失败,Android资源链接失败
  17. 计算机职业学校教学论文,中等职业学校计算机教学论文
  18. 云时代的“双态IT”运维思路
  19. Task already scheduled or cancelled(用Timer,TimeTask实现定时器功能)
  20. 树莓派的ssh连接配置

热门文章

  1. 原型设计工具的对比评测记录(一)
  2. 支撑4.5亿活跃用户的WhatsApp架构概览
  3. 今时今日,C还适合当下之所需么?
  4. 再见腾讯,创业我来了!!!
  5. vue 组件间传值、兄弟组件 、bus方式 ( 1 分钟看懂 )
  6. 阿里云服务器 CentOS 7上-- Docker 安装 网关(API-Getway)--KONG
  7. 解决:Failed to execute goal on project aopcore: Could not resolve dependencies for project com.cmos:
  8. Spring事务传播行为7种类型 --- 看一遍就能记住!
  9. xml编辑无提示?这么破!
  10. Centos7 安装OpenTSDB