窗体与数据帧分析

窗体与数据帧分析



一、wireshark的安装

链接: https://pan.baidu.com/s/18jMDSNe6Za-iMccuTsvm9w
提取码:vbli
下载完成后,我们开始安装;
在这里插入图片描述
双击Wireshark-win64-3.2.7文件,进入安装界面,双击Next.
在这里插入图片描述
同意协定,点击I agree.
在这里插入图片描述
双击Next
在这里插入图片描述
一直点击Next,确定路径(可自定义),点击next,然后install
在这里插入图片描述
等待安装
在这里插入图片描述
安装完成,点击finish
在这里插入图片描述
最后,我们在桌面创建一快捷方式,方便使用。

在这里插入图片描述

至此,wireshark就已经安装完成了


二、用C编写一个命令行/控制台

本部分内容: C# 编写一个命令行/控制台 hello world 程序,实现如下功能:在屏幕上连续输出 50 行 “ hello cqjtu!重交物联2018级 ” ;同时打开一个网络 UDP 套接字,向室友电脑或树莓派发送这 50 行消息

1、命令行/控制台程序

这里需要用到编译工具visual studio2019,由于前面已经安装完成,这里不再详细阐述其安装操作。提供下载途径,如果有需要可以参考。
博客: https://blog.csdn.net/QWERTYzxw/article/details/109080487
安装教程: visual studio2019的安装以及使用图文步骤详解
接下来,我们操作如何用C#编写一个命令行/控制台功能程序。
打开Visual Studio2019,点击“创建新项目”,选择“控制台应用(.NET Framework) ”,然后点击“下一步”。
在这里插入图片描述
这里我们找不到c#的控制台应用,“找不到完全匹配项”,我们可以选择点击“安装多个工具和功能”。
在这里插入图片描述
点击选择“.Net桌面开发”,进行安装。
在这里插入图片描述
等待安装
在这里插入图片描述
安装完成后,点击启动,进入到下面界面看到我们所需的控制台。
在这里插入图片描述
选择控制台应用,点击下一步,创建新项目。在项目名称填入ConsolTest(可自行定义);自由选择路径,然后点击“创建”。
在这里插入图片描述
创建完成后,显示界面如下:
在这里插入图片描述

2、功能的实现

在main函数后面输入下面代码。

for(int i = 0; i < 50; i++)
            {
    
    
                Console.WriteLine("第{0}行:hello cqjtu!重交物联2018级", (i + 1));
            }
            System.Console.ReadKey();

在这里插入图片描述
点击运行,结果如下:
在这里插入图片描述
至此,我们的控制台创建完成,并且实现了在屏幕上连续输出50行“hello cqjtu!重交物联2018级”的功能。

3、对UDP协议的了解

当前协议分为:UDP与TCP两类
UDP是无连接协议,客户端和服务器通信之前不需要建立握手连接;
UDP没有应答机制,所以也没有重发机制,很大的可能会造成丢包、收到重复包、乱序的情况;
UDP可以实现局域网广播功能,即某个主机可以向所有在同个子网的主机发送数据…
如果相对UDP有更加深入的了解,可以参考以下资料。
资料1: UDP-文库
资料2:UDP与TCP对比

4、UDP通信

客户端发送,服务器接收。
首先在自己电脑上创建一个新项目client,将下列代码复制粘贴进去;
客户端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Client
{
    
    
    class Program
    {
    
    
        static void Main(string[] args)
        {
    
    
            //提示信息
            Console.WriteLine("按下任意按键开始发送...");
            Console.ReadKey();
            //做好链接准备
            UdpClient client = new UdpClient();  //实例一个端口
            IPAddress remoteIP = IPAddress.Parse("10.60.202.32");  //假设发送给这个IP
            int remotePort = 11000;  //设置端口号
            IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort);  //实例化一个远程端点 
            string sendString = "hello cqjtu!重交物联2018级";//要发送的数据:hello cqjtu!重交物联2018级
            for (int i = 0; i < 50; i++)
            {
    
    
                //定义发送的字节数组
                //将字符串转化为字节并存储到字节数组中
                byte[] sendData = null;
                sendData = Encoding.Default.GetBytes(sendString);

                client.Send(sendData, sendData.Length, remotePoint);//将数据发送到远程端点 
            }
            client.Close();//关闭连接

            //提示信息
            Console.WriteLine("");
            Console.WriteLine("数据发送成功,按任意键退出...");
            System.Console.ReadKey();
        }
    }
}

然后在室友电脑上创建一个server的项目,将下列代码复制粘贴进去;
服务器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Server
{
    
    
    class Program
    {
    
    
        static void Main(string[] args)
        {
    
    
            int i = 0;
            UdpClient client = new UdpClient(11000);
            string receiveString = null;
            byte[] receiveData = null;
            //实例化一个远程端点,IP和端口可以随意指定,等调用client.Receive(ref remotePoint)时会将该端点改成真正发送端端点 
            IPEndPoint remotePoint = new IPEndPoint(IPAddress.Any, 0);
            while (true)
            {
    
    
                i++;
                Console.WriteLine("正在准备接收第 {0} 条数据...",i);
                receiveData = client.Receive(ref remotePoint);//接收数据 
                receiveString = Encoding.Default.GetString(receiveData);
                Console.WriteLine(receiveString);
                Console.WriteLine("第 {0} 条数据接收完毕!",i);
                Console.WriteLine("");
            }
            //client.Close();//关闭连接,如果没有死循环的话,实例client后需要关闭。
        }
    }
}

5、编译结果

客户端:
在这里插入图片描述
服务器:
在这里插入图片描述

6、wireshark抓包

双击桌面下载的wireshark
由于网络连接为以太网,所以选择以太网2
在这里插入图片描述
在这里插入图片描述
我们可以看到wireshark在一直抓包,点击红色按钮停止抓包
在这里插入图片描述
重新编译客户端与服务器,不发送
在这里插入图片描述
点击File下面的图标,不保存之前抓到的包
在这里插入图片描述
然后开始任意键发送,发送完后。点击wireshark红色按钮,停止抓包
在这里插入图片描述
在“过滤器”里面输入UDP,会显示下面内容
在这里插入图片描述

7、数据帧结构分析

大家都知道我们从应用层发出的消息会经由传输层,网络层,数据链路层,物理层,它们每到一层都会转变形式。
可参考链接: https://zhuanlan.zhihu.com/p/146188551.
下面这张图片,让我们详细了解数据帧结构
在这里插入图片描述
EthernetII帧结构
EthernetII帧结构。有几种不同类型的帧结构,尽管它们格式和最大传输单元不同,但却能够共存于相同的物理媒体上。EthernetII 帧(又称DIX帧)是目前使用最广的以太帧。图21显示了Ethernet II帧结构(该帧前后的辅助字段没有显示)。与802.3以太帧结构相比,它较为简单。其中的以太类型字段标识了封装了该帧数据中的较高层协议。例如,以太类型值为0x0800指示了该帧包含了IPv4数据报,0x0806表明指示了该帧包含了ARP帧,0x8100指示了该帧包含了IEEE 802.1Q帧。
在这里插入图片描述
目的地址(Destination):数据的接收方,这里是10.60.202.32;
在这里插入图片描述
源地址:(Source):数据的发送方,这里是10.60.190.83
在这里插入图片描述
数据类型(Type):分为 IP(0800) 包和 ARP(0806) 包,包是 0800 ,所以是 IP 包
在这里插入图片描述
数据:后面三排,上层(网络层)传下来的一个 IP 包,数据部分又分为数据部分和填充部分,当这个 IP 包的长度小于 46 个字节,比如数据部分长度为 30 ,那么填充部分(无用信息)就是 16 个字节,保证这个帧的总长度最短为 64 个字节,如果数据部分长度为50,那么填充部分就为 0 个字节,最后,数据(数据部分 + 填充部分)的长度最长为 1500 个字节,不能过大,所以帧的总长度最长为 1518 字节,抓取的所有包,都不会超过这个长度。
在这里插入图片描述
校验码:帧的末尾有 4 字节的校验码,但是抓包软件会自动舍去
ip数据报
在这里插入图片描述
下面我们任意一个数据进行分析
在这里插入图片描述
Version(版本号):分为 IPv4 和 IPv6 现在普遍都用的 IPv4 ,所以值为 4 ,1 个字节
在这里插入图片描述
HLen(ip报头长度):32位字的报头长度(HLEN)
在这里插入图片描述
TOS(级别):服务类型描述数据报将如何被处理,比如优先发送等,大多数都是默认为 0
在这里插入图片描述
Datagram Total Length(总长度):包括报头和数据的数据包长度
在这里插入图片描述
identifier(标识):唯一的 IP 数据包值
在这里插入图片描述
Flags(标志):说明是否有数据被分段,一条一条的发送多个数据包,每个包的数据很小,没有被分段,所以这里数值为 0
在这里插入图片描述
Fragmentation Offset(分段偏移):如果数据包在装人帧时太大,则需要进行分段和重组,这里没有分段,所以偏移量为 0
在这里插入图片描述
TTL(存活期):存活期是在数据包产生时建立在其内部的一个设置,如果这个数据包在这个TTL到期时仍没有到达它要去的目的地,那么它将被丢弃,这个设置将防止IP包在寻找目的地的时候在网络中不断循环,每经过一个路由器,它的值就减一,这里它的值为 128 ,也就是 128 个生存期
在这里插入图片描述
Protocol(协议):上层协议的端口( TCP 是端口 6;UDP 是端口 17) ,同样也支持网络层协议,如ARP和ICMP,这里值为 17 ,也就是 UDP 协议
在这里插入图片描述
Header Checksum(校验码):只针对报头的循环冗余校验(CRC)
在这里插入图片描述
Source Address(源地址):消息发送者的 ip 地址,这里是10.60.190.83
在这里插入图片描述
Destination Address(目的地址):消息接收者的 ip 地址,这里是10.60.202.32
在这里插入图片描述
ip包头的第六行:用于网络检测、调试、安全以及更多的内容
数据包
长度为 34 字节,对应的十六进制就是蓝色的区域了,这就是我们要发送的数据:第n行:hello cqjtu!重交物联2018级
在这里插入图片描述
至此,数据帧的结构就分析完了,想要了解更多详情,可以见参考资料。

三、vs2019的C#编写一个简单的Form窗口程序

本部分内容:用 VS2019 的 C# 编写一个简单的 Form 窗口程序,有一个文本框 textEdit 和一个发送按钮 button ,运行程序后,可以在文本框里输入文字,如 “ hello cqjtu!重交物联2018级 ” ,点击 button ,将这些文字发送给室友电脑或树莓派,采用 TCP 套接字

1、创建窗口

创建窗口(创建步骤大致同上)
打开VS2019,选择创建新项目,选择Windows窗体应用,点击下一步
在这里插入图片描述
配置新项目,自定义项目名称、路径,点击创建
在这里插入图片描述
创建完成
在这里插入图片描述
至此,窗口的创建就完成了。

2、设计界面

摆放控件,从工具箱内拖 2 个 TextBox 和 1 个 Button 控件
在这里插入图片描述
设置消息输入框属性
左键选中最下面的 TextBox ,并在右下角的属性中找到 Font 属性,并点击 “ … ” ,界面内可以设置字体样式。
在这里插入图片描述
在设计属性中的(Name)这里默认的 textBox1 ,也可以更改,但不能重复,唯一标识,这是控件的编号,用于代码编写的时候识别,不能用中文。
在这里插入图片描述
在布局这里,Location 是指控件左上角顶点基于窗口所在的位置,Size 是指控件的长和宽,可以自行设置
在这里插入图片描述
设置消息显示界面属性
选中一个 TextBox ,并点击黑色的小三角按钮,可以将单行文本框设置为多行文本框;找到 ScrollBars 属性,设置参数为 Vertical
在这里插入图片描述
设置边界样式:找到 BorderStyle ,参数设置为 FixedSingle
在这里插入图片描述
找到 Enabled 属性,参数设为 False
在这里插入图片描述
可以根据自己需求设置文本属性
左键点击button按钮,找到 Text 属性,参数输入为 “ 发送 ” ,则控件上就会显示输入的“发送”字样
在这里插入图片描述
设置窗体属性
左击窗体选中它,在右下角的属性中找到 Text 属性,编辑为 “ 客户端 ” ,然后窗体的左上角,就显示为 “ 客户端 ”。
在这里插入图片描述

选中AcceptButton 属性,下拉框选中这个 button1 按钮,设置完这个属性后,当我们最后执行这个程序后,按下回车键 相当于点击这个按钮。
在这里插入图片描述
至此,控件就基本设置完成了。

3、窗体程序代码

需要创建的项目方法参照上面内容,这里忽略。
双击界面按钮,VS会自动跳到代码区域。
在这里插入图片描述
button1_Click 函数内复制粘贴如下代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    
    
    public partial class Form1 : Form
    {
    
    
        public Form1()
        {
    
    
            InitializeComponent();
        }

         public void button1_Click(object sender, EventArgs e)
        {
    
    
            try
            {
    
    
                /*
                 * 显示当前时间
                 */
                string str = "The current time: ";
                str += DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                textBox2.AppendText(str + Environment.NewLine);
                /*
                 * 做好连接准备
                 */
                int port = 2000;
                string host = "10.60.202.32";//我室友的IP地址
                IPAddress ip = IPAddress.Parse(host);
                IPEndPoint ipe = new IPEndPoint(ip, port);//把ip和端口转化为IPEndPoint实例
                Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket
                /*
                 * 开始连接
                 */
                str = "Connect to server...";
                textBox2.AppendText(str + Environment.NewLine);
                c.Connect(ipe);//连接到服务器
                /*
                 *发送消息 
                 */
                string sendStr = textBox1.Text;
                str = "The message content: " + sendStr;
                textBox2.AppendText(str + Environment.NewLine);
                byte[] bs = Encoding.UTF8.GetBytes(sendStr);
                str = "Send the message to the server...";
                textBox2.AppendText(str + Environment.NewLine);
                c.Send(bs, bs.Length, 0);//发送信息
                /*
                 * 接收服务器端的反馈信息
                 */
                string recvStr = "";
                byte[] recvBytes = new byte[1024];
                int bytes;
                bytes = c.Receive(recvBytes, recvBytes.Length, 0);//从服务器端接受返回信息
                recvStr += Encoding.UTF8.GetString(recvBytes, 0, bytes);
                str = "The server feedback: " + recvStr;//显示服务器返回信息
                textBox2.AppendText(str + Environment.NewLine);
                /*
                 * 关闭socket
                 */
                c.Close();
            }
            catch (ArgumentNullException f)
            {
    
    
                string str = "ArgumentNullException: " + f.ToString();
                textBox2.AppendText(str + Environment.NewLine);
            }
            catch (SocketException f)
            {
    
    
                string str = "ArgumentNullException: " + f.ToString();
                textBox2.AppendText(str + Environment.NewLine);
            }
            textBox2.AppendText("" + Environment.NewLine);
            textBox1.Text = "";
        }
    }
}

复制下面 main 函数内的代码,并粘贴进你自己的 main 函数内

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    
    
    class Program
    {
    
    
        static void Main(string[] args)
        {
    
    
            /*
             * 做好连接准备
             */
            int i = 0;
            int port = 2000;
            string host = "10.60.202.32";
            IPAddress ip = IPAddress.Parse(host);
            IPEndPoint ipe = new IPEndPoint(ip, port);
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个Socket类
            s.Bind(ipe);//绑定2000端口
            /*
             * 循环监听并处理消息
             */
            while (true)
            {
    
    
                i++;
                try
                {
    
    
                    Console.Write("Perform operations {0} :",i);
                    Console.WriteLine("\t-----------------------------------------------");
                    s.Listen(0);//开始监听
                    Console.WriteLine("1. Wait for connect...");
                    /*
                     * 实例一个新的socket端口
                     */
                    Socket temp = s.Accept();//为新建连接创建新的Socket。
                    Console.WriteLine("2. Get a connect");
                    /*
                     * 接收客户端发的消息并做解码处理
                     */
                    string recvStr = "";
                    byte[] recvBytes = new byte[1024];
                    int bytes;
                    bytes = temp.Receive(recvBytes, recvBytes.Length, 0);//从客户端接受信息
                    recvStr += Encoding.UTF8.GetString(recvBytes, 0, bytes);
                    Console.WriteLine("3. Server Get Message:{0}", recvStr);//把客户端传来的信息显示出来
                    /*
                     * 返回给客户端连接成功的消息
                     */
                    string sendStr = "Ok!Client send message sucessful!";
                    byte[] bs = Encoding.UTF8.GetBytes(sendStr);
                    temp.Send(bs, bs.Length, 0);//返回客户端成功信息
                    /*
                     * 关闭端口
                     */
                    temp.Close();
                    Console.WriteLine("4. Completed...");
                    Console.WriteLine("-----------------------------------------------------------------------");
                    Console.WriteLine("");
                    //s.Close();//关闭socket(由于再死循环中,所以不用写,但如果是单个接收,实例socket并完成任务后需关闭)
                }
                catch (ArgumentNullException e)
                {
    
    
                    Console.WriteLine("ArgumentNullException: {0}", e);
                }
                catch (SocketException e)
                {
    
    
                    Console.WriteLine("SocketException: {0}", e);
                }
            }
        }
    }
}

4、结果演示

客户端:
在这里插入图片描述
在这里插入图片描述

服务器端:
在这里插入图片描述
在这里插入图片描述

5、数据帧分析

参考上面抓包方式,进行抓包分析。由于上面已有抓包分析数据帧结构的详细步骤,这里不再阐述。这里主要说明一下UDP与TCP协议的区别。
UDP:
在这里插入图片描述
第三行:Internet Protocl Version 4:IPv4协议
第四行:User Datagram Protocol:UDP协议
TCP:
在这里插入图片描述
第三行:Internet Protocl Version 4:IPv4协议
第四行:Transmission Control Protocol:TCP协议
由此可见,它们区别在于第四行,第三行都是 IPv4 协议
p 包头也是 45 00 开头,对比一下第二部分对 ip 包的分析,这个 ip 包头也是 45 00 开头,所以一个 ip 包的前两个字节一定是 45 00
在这里插入图片描述
生存期也是 128 ,一个包的生存期基本上都是默认的数值 128 ,而这里的协议号是 6 ,这就是 TCP 的协议号,第二部分的协议号是 17 ,是 UDP 的
在这里插入图片描述
其他的就同UDP协议雷同了。



四、总结与参考资料

1、总结

能够创建窗体,用窗体进行消息的发送与接收;了解到UDP与TCP协议是怎么进行套字的;对我们日常发送的消息是怎么进行有了深刻了解;对数据帧的认识也更加深刻。

2、参考资料

1: 分析数据链路层帧结构实验.
2: UDP-文库.
3: 数据帧结构.
4: 数据帧.
5: UDP数据的发送与接收.
6: 网络编程之UDP套接字.

猜你喜欢

转载自blog.csdn.net/QWERTYzxw/article/details/109391347