不管用的是什么样的协议方式,基本通讯的原理
到底层 都是 byte[]数组 传递。

1.协议的定义
协议本身只是 通讯时候 前后端 定义的变量类型和顺序的集合。
比如说,要做一个登陆的消息传递,
需要传递的内容是帐号密码

public class MsgLogin
{public string m_strIDName = null;public string m_strPassWord = null;
}

前后端都确认好,使用帐号密码登陆,那么这样一个类,就可以称之为一个协议了。

那么客户端填好帐号密码后,转成byte[] 通过Socket发送到服务器,服务器解析这个消息,得到帐号密码,就完成了一次通讯。

byte[] 的内容就是 m_strIDName转换成的byte[] 拼接上 m_strPassWord转换成的byte[]

2.消息号
例如登入,客户端通知服务器要登录了
那么服务器对应的也要回复给客户端,登录是成功或者失败。
那么服务器可以定义通知客户端的协议是:

public class MsgLoginCallBack
{public bool m_isSuc = false;
}

那么问题就来了,一个游戏里,可以会有好多的通讯,比如购买,点击,广播之类的。 而消息本身只是一串byte[]的内容,
接受端要知道这条消息要干嘛,那就需要消息号。

消息号本身只需要做一个唯一的标记,例如可以做一个枚举:

public enum OperateCode : ushort
{C2S_LOGIN = 1,S2C_LOGIN = 2
}

C2S = Client to Server
S2C = Server to Client
(这个基本上约定俗成)
那么代码就变成了

public class MsgLogin
{public OperateCode m_opCode = OperateCode.C2S_LOGIN;public string m_strIDName = null;public string m_strPassWord = null;
}public class MsgLoginCallBack
{public OperateCode m_opCode = OperateCode.S2C_LOGIN ;public bool m_isSuc = false;
}

客户端和服务器统一 一套消息号
这样互相解析第一个字段m_opCode 就能知道当前这条消息,对于本次通讯要做什么事了。
3.数据包的组装
前面说到通讯用到的是byte[]
那么怎么组装和解析这个byte[]那?
google的protobuf提供了很好的解决方案,可以百度一下参考。
这里说一下基本原理,也叫做 字节序,也是比较常用的一套方案。

先说一下消息包的组成。
一般分为 包头 和 包体。

包头 包含 消息号 和 包体长度
包体 包含 各种需要通讯的内容,也就是上面的类包含的变量。

例如:
包头部分:

内容 类型 长度
消息号 ushort 2
包体长度 ushort 2

那么包头的长度就是 2+2=4

包体:
像是上面的登录消息,是2个string,但是帐号密码的长度,我们是不知道的。那就需要做一件事就是 取得string的长度放在byte[]里string内容前面,告诉接收方,我接下去要解析的这个string字段的长度。

public class MsgLogin
{public string m_strIDName = null;public string m_strPassWord = null;
}

以这个消息为例
消息的构成就是

内容 类型 长度
消息号 ushort 2
包体长度 ushort m_strIDName长度 + m_strPassWord长度
m_strIDName长度 ushort 转换byte[]后取长度
m_strIDName内容 byte[] byte[]本身
m_strPassWord长度 ushort 转换byte[]后取长度
m_strPassWord内容 byte[] byte[]本身
    public class MsgLogin{public OperateCode m_opCode = OperateCode.C2S_LOGIN;public string m_strIDName = null;public string m_strPassWord = null;public byte[] Package(){m_strIDName = "1234";m_strPassWord = "4321";byte[] bytesOpcode = BitConverter.GetBytes((ushort)m_opCode);byte[] bytesIDName = System.Text.Encoding.UTF8.GetBytes(m_strIDName);byte[] bytesPassWord = System.Text.Encoding.UTF8.GetBytes(m_strIDName);/*Buffer.BlockCopy拼接byte[]这里简写帐号长度 = bytesIDName.Length密码长度 = bytesPassWord.Length包体长度 = bytesIDName.Length + bytesPassWord.Length包头:[bytesOpcode + 包体长度]包体;[帐号长度 + bytesIDName + 密码长度 + bytesPassWord]消息包 = 包头 + 包体*/return ***;}}

3.数据包的解析
最终得到byte[]发送,
接收到的时候
取得1,2位 解析 得到消息号
取得3,4位 解析 得到包体长度
按照包体长度向后取到整个包体
在包体中 解析 包体的1,2位解析得帐号(假定长度是ushort)

2(第一个string长度) + 帐号长度 + 1
2(第一个string长度) + 帐号长度 + 2
取得这2位 得到密码长度后,继续解析密码

这样一套 组装 和 解析的概念 就完成了。


程序学无止尽。
欢迎大家沟通,有啥不明确的,或者不对的,也可以和我私聊
我的QQ 334524067 神一般的狄狄

简单易懂的Socket TCP网络通讯知识-消息协议和数据包相关推荐

  1. TCP局域网 通讯 的消息发送

    import java.io.*; import java.net.ServerSocket; import java.net.Socket;/*** 初学者TCP局域网 通讯 的消息发送* TCP ...

  2. java 网络通讯_JAVA编程实现TCP网络通讯的方法示例

    本文实例讲述了JAVA编程实现TCP网络通讯的方法.分享给大家供大家参考,具体如下: TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字 ...

  3. 网络排错模型之我见----模型,基线,协议,数据包

    网络故障检测和排除的方法自己总结了下,大概有三种: A ISO七层模型法(包括什么自上而下,自下而上,分而治之等) B 跟踪流量路径法 C 对比替代法 排错的功夫也大概分为三个层次: 1.就是使用对比 ...

  4. 计算机网络实验一——应用协议与数据包分析

    计算机网络实验一--应用协议与数据包分析 一.实验题目 二.实验内容 三.实验原理 1.HTTP 的工作原理 2.HTTP 报文格式 四.实验步骤 1.截获报文步骤 2.TCP连接分析 3.HTTP简 ...

  5. TCP/IP学习(30)——L2数据链路层的数据包处理详细流程

    原文地址:TCP/IP学习(30)--L2数据链路层的数据包处理详细流程 作者:GFree_Wind 本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝 ...

  6. tshark 解析pcap中带TLS协议的数据包

    tshark的简单用法参考:tshark解析本地pcap数据包提取五元组{src_ip,src_port,proto,dst_ip,dst_port}与时间戳,包长 详细用法:官方DOC 比如提取一个 ...

  7. 基于TCP流协议的数据包通讯

    Fanxiushu   2016-02-04,引用或转载请注明原始作者. TCP通讯是流协议,它不像UDP那样基于包为边界的通讯方式, TCP流式协议,举个简单例子,一端用send 分别发送 100, ...

  8. Socket编程 - 网络基础知识

    API编程部分:http://www.cnblogs.com/Jimmy1988/p/7895213.html 1. 协议简介 此处,我们主要介绍Linux编程常用的三种协议(TCP/UDP/IP), ...

  9. C# TCP网络编程5(分包和粘包二)

    一:TCP粘包产生的原理 1,TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾.出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能 ...

最新文章

  1. Google Colab——用谷歌免费GPU跑你的深度学习代码
  2. 有哪些可以免登录的视频会议软件/服务?
  3. 2.1.2 数据通信基础知识
  4. linux创建进程fork函数和vfork函数
  5. delphi里用java_如何在整个Delphi应用程序中使用ID
  6. java nextlong_Java Random nextLong()方法与示例
  7. Linux操作系统安装ELK stack日志管理系统--(1)Logstash和Filebeat的安装与使用
  8. 中国居民人均财富36.6万元,你达标了吗?
  9. LS-DYNA系列_Mie-Gruneisen状态方程
  10. Android 蓝牙HID协议(基于BR蓝牙)连接流程分析--framework-jni-btif-bta-btm-hci -- 全网最详细(一)
  11. 单片机应用系统设计技术——基于51单片机的火灾温度烟雾报警器设计
  12. springboot项目在服务器怎么启动,springboot在服务器上启动的几种方式,亲测通过!...
  13. 110 Ruby 版本管理器【Rails后端开发训练营】
  14. 【杂谈与乱码】我们过度解读了鲁迅先生了么?
  15. [pyecharts学习笔记]——页面组件 Page(顺序多图,将多个图将汇总到一个页面)
  16. Google还能做什么?(转贴)
  17. 手记:配置IIS服务器,支持sis、SISX、3GP、ADP、AMR、JAD、JAR、MMF、MFM、PMD、UMD等文件下载...
  18. 网易云音乐编码_音乐编码依据
  19. 阿里程序媛凉安成长记:现世安稳,线上安稳
  20. 数据库update(动态更新)-SqlServer

热门文章

  1. 多线程爬虫获取A股历史行情数据!股票量化分析工具QTYX-V2.2.3
  2. 谢宝友:深入理解RCU之六:分级RCU基础
  3. cad打印去掉边框_CAD打印图纸时如何去除白色的边框
  4. VM-虚拟机装苹果系统
  5. jQurey 筛选 查找
  6. 手把手 | 事理图谱,下一代知识图谱
  7. 【ParaView教程】1.1 发展和筹资
  8. 狼人杀(身份随机分配)
  9. 吴师兄领证之前谈了多少个女朋友?
  10. 医院业务系统设计(四) --- 患者管理之分诊系统