简单易懂的Socket TCP网络通讯知识-消息协议和数据包
不管用的是什么样的协议方式,基本通讯的原理
到底层 都是 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网络通讯知识-消息协议和数据包相关推荐
- TCP局域网 通讯 的消息发送
import java.io.*; import java.net.ServerSocket; import java.net.Socket;/*** 初学者TCP局域网 通讯 的消息发送* TCP ...
- java 网络通讯_JAVA编程实现TCP网络通讯的方法示例
本文实例讲述了JAVA编程实现TCP网络通讯的方法.分享给大家供大家参考,具体如下: TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字 ...
- 网络排错模型之我见----模型,基线,协议,数据包
网络故障检测和排除的方法自己总结了下,大概有三种: A ISO七层模型法(包括什么自上而下,自下而上,分而治之等) B 跟踪流量路径法 C 对比替代法 排错的功夫也大概分为三个层次: 1.就是使用对比 ...
- 计算机网络实验一——应用协议与数据包分析
计算机网络实验一--应用协议与数据包分析 一.实验题目 二.实验内容 三.实验原理 1.HTTP 的工作原理 2.HTTP 报文格式 四.实验步骤 1.截获报文步骤 2.TCP连接分析 3.HTTP简 ...
- TCP/IP学习(30)——L2数据链路层的数据包处理详细流程
原文地址:TCP/IP学习(30)--L2数据链路层的数据包处理详细流程 作者:GFree_Wind 本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝 ...
- tshark 解析pcap中带TLS协议的数据包
tshark的简单用法参考:tshark解析本地pcap数据包提取五元组{src_ip,src_port,proto,dst_ip,dst_port}与时间戳,包长 详细用法:官方DOC 比如提取一个 ...
- 基于TCP流协议的数据包通讯
Fanxiushu 2016-02-04,引用或转载请注明原始作者. TCP通讯是流协议,它不像UDP那样基于包为边界的通讯方式, TCP流式协议,举个简单例子,一端用send 分别发送 100, ...
- Socket编程 - 网络基础知识
API编程部分:http://www.cnblogs.com/Jimmy1988/p/7895213.html 1. 协议简介 此处,我们主要介绍Linux编程常用的三种协议(TCP/UDP/IP), ...
- C# TCP网络编程5(分包和粘包二)
一:TCP粘包产生的原理 1,TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾.出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能 ...
最新文章
- Google Colab——用谷歌免费GPU跑你的深度学习代码
- 有哪些可以免登录的视频会议软件/服务?
- 2.1.2 数据通信基础知识
- linux创建进程fork函数和vfork函数
- delphi里用java_如何在整个Delphi应用程序中使用ID
- java nextlong_Java Random nextLong()方法与示例
- Linux操作系统安装ELK stack日志管理系统--(1)Logstash和Filebeat的安装与使用
- 中国居民人均财富36.6万元,你达标了吗?
- LS-DYNA系列_Mie-Gruneisen状态方程
- Android 蓝牙HID协议(基于BR蓝牙)连接流程分析--framework-jni-btif-bta-btm-hci -- 全网最详细(一)
- 单片机应用系统设计技术——基于51单片机的火灾温度烟雾报警器设计
- springboot项目在服务器怎么启动,springboot在服务器上启动的几种方式,亲测通过!...
- 110 Ruby 版本管理器【Rails后端开发训练营】
- 【杂谈与乱码】我们过度解读了鲁迅先生了么?
- [pyecharts学习笔记]——页面组件 Page(顺序多图,将多个图将汇总到一个页面)
- Google还能做什么?(转贴)
- 手记:配置IIS服务器,支持sis、SISX、3GP、ADP、AMR、JAD、JAR、MMF、MFM、PMD、UMD等文件下载...
- 网易云音乐编码_音乐编码依据
- 阿里程序媛凉安成长记:现世安稳,线上安稳
- 数据库update(动态更新)-SqlServer