概述
UDP协议包校验和小工具设计与实现
原代码文件链接:
实现的功能:
C sharp实现界面的设计,UDP校验和的计算,UDP数据包的生成与发送,数据的保存。总体的代码在主页,有兴趣的可以一起学习交流。
存在问题:
界面的设计比较的简单,图标没进行更换,数据的保存是覆盖性的,追加性数据保存会更好些。UDP数据的接收端并不是自己写的,而是通过网络小助手进行的数据接收。
校验和
校验和的计算方法大同小异,基本的方法都是对应字段二进制反码累加和进行相加。当然了在计算校验和时,二进制相加会出现溢出所以要做溢出处理。
UDP的校验和主要由:UDP首部,伪首部,数据三个部分组成,UDP检验和的计算需要通过将三部分的相应字段转换成二进制反码相加求和。
(1)伪首部:源IP地址,目的IP地址,协议填充字段,协议,UDP数据部分。
(2)首部: 源端口,目的端口,UDP数据部分,检验和。
(3)数据:UDP最小的长度为8bit
源代码:
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.IO;
namespace UDP_Protocol_design
{
public partial class Form1 : Form
{
string[] udphead = new string[14];
string allSum;
public Form1() //窗体的组件随界面的大小缩放
{
InitializeComponent();
}
private float X, Y; //获得控件的长度、宽度、位置、字体大小的数据
private void SetTag(Control cons) //Control类,定义控件的基类
{
foreach (Control con in cons.Controls) //获取或设置包含有关控件的数据的对象
{
con.Tag = con.Width + ":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size;
if (con.Controls.Count > 0)
SetTag(con); //递归算法
}
} //实现控件以及字体的缩放
private void SetControls(float newx, float newy, Control cons)
{
foreach (Control con in cons.Controls)
{
string[] mytag = con.Tag.ToString().Split(new char[] { ':' });
float a = Convert.ToSingle(mytag[0]) * newx;
con.Width = (int)a;
a = Convert.ToSingle(mytag[1]) * newy;
con.Height = (int)(a);
a = Convert.ToSingle(mytag[2]) * newx;
con.Left = (int)(a);
a = Convert.ToSingle(mytag[3]) * newy;
con.Top = (int)(a);
Single currentSize = Convert.ToSingle(mytag[4]) * newy;
con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
if (con.Controls.Count > 0)
{
SetControls(newx, newy, con); //递归
}
}
}
private void MyForm_Resize(object sender, EventArgs e)
{
float newx = (this.Width) / X; //当前宽度与变化前宽度之比
float newy = this.Height / Y; //当前高度与变化前宽度之
SetControls(newx, newy, this);
this.Text = ("UDP协议包自动生工具设计"); //显示窗体的标签
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.Resize += new EventHandler(MyForm_Resize);
X = this.Width;
Y = this.Height;
SetTag(this);
} //窗体的组件随界面的而缩放
private void Label1_Click(object sender, EventArgs e)
{
}
private void Button1_Click(object sender, EventArgs e) //校验和的入口函数
{
if (!InfoCheck())
{
return;
}
udphead[9] = "0000";
CacuSum(udphead[0], 1);
string overflow = "";
if (allSum.Length > 4) //溢出处理
{
for (int i = 0; i < allSum.Length - 4; i++)
{
overflow += allSum[i];
}
}
allSum = allSum.Remove(0, allSum.Length - 4);
string checksum2 = ConvertHexToBin(TwoSum(overflow, allSum));
string cumsum = Cumulativesum(TwoSum(overflow, allSum));
textBox14.Text = checksum2;
textBox13.Text = cumsum;
}
private bool InfoCheck()
{
DialogResult result;
string Source = textBox4.Text; //源IP地址
string Destination = textBox5.Text; //目的IP地址
if (!IsIP(Source) || !IsIP(Destination)) //判断输入的IP是否合法
{
MessageBoxButtons buttons = MessageBoxButtons.OK;
string message = "ip地址不合法";
string caption = "提示";
result =MessageBox.Show(this, message, caption, buttons);
return false;
}
string Protocol_fill, Protocol_udp; //协议的字段填充值的定义
string data1, data2, data3, data4, data5, data6, data7, data8;
try
{ //UDP伪首部部分
Protocol_fill = Convert.ToString(Convert.ToInt32(textBox6.Text), 16).PadLeft(2, '0');
Protocol_udp = Convert.ToString(Convert.ToInt32(textBox22.Text), 16).PadLeft(2, '0');
udphead[4] = Protocol_fill + Protocol_udp;
udphead[5] = Convert.ToString(Convert.ToInt32(textBox8. Text), 16).PadLeft(4, '0');
udphead[6] = Convert.ToString(Convert.ToInt32(textBox9. Text), 16).PadLeft(4, '0');
udphead[7] = Convert.ToString(Convert.ToInt32(textBox10.Text), 16).PadLeft(4, '0');
udphead[8] = Convert.ToString(Convert.ToInt32(textBox11.Text), 16).PadLeft(4, '0');
//udphead[9] = Convert.ToString(Convert.ToInt32(textBox12.Text), 16).PadLeft(4, '0');
//UDP数据部分
data1 = textBox1.Text;
data2 = textBox7.Text;
data3 = textBox16.Text;
data4 = textBox17.Text;
data5 = textBox21.Text;
data6 = textBox20.Text;
data7 = textBox19.Text;
data8 = textBox18.Text;
//UDP部分的进制转化获取数据转换为十六进制
//data1 = Convert.ToString(Convert.ToInt32(textBox1. Text), 16).PadLeft(2, '0');
//data2 = Convert.ToString(Convert.ToInt32(textBox7. Text), 16).PadLeft(2, '0');
//data3 = Convert.ToString(Convert.ToInt32(textBox16.Text), 16).PadLeft(2, '0');
//data4 = Convert.ToString(Convert.ToInt32(textBox17.Text), 16).PadLeft(2, '0');
//data5 = Convert.ToString(Convert.ToInt32(textBox21.Text), 16).PadLeft(2, '0');
//data6 = Convert.ToString(Convert.ToInt32(textBox20.Text), 16).PadLeft(2, '0');
//data7 = Convert.ToString(Convert.ToInt32(textBox19.Text), 16).PadLeft(2, '0');
//data8 = Convert.ToString(Convert.ToInt32(textBox18.Text), 16).PadLeft(2, '0');
udphead[10] = data1+data2;
udphead[11] = data3+data4;
udphead[12] = data5+data6;
udphead[13] = data7+data8;
}
catch (Exception)
{
string message = "输入不合法";
string caption = "提示";
result = MessageBox.Show(this, message, caption, MessageBoxButtons.OK);
return false;
}
string[] udpSource = Source.Split('.');
string[] udpDestination = Destination.Split('.');
for (int i = 0; i < 4; i++) //十进制转十六进制
{
udpSource[i] = Convert.ToString(Convert.ToInt32(udpSource[i]), 16).PadLeft(2, '0');
}
for (int i = 0; i < 4; i++) //十进制转十六进制
{
udpDestination[i] = Convert.ToString(Convert.ToInt32(udpDestination[i]), 16).PadLeft(2, '0');
}
udphead[0] = udpSource[0] + udpSource[1]; //UDP源IP地址
udphead[1] = udpSource[2] + udpSource[3];
udphead[2] = udpDestination[0] + udpDestination[1]; //UDP目的IP地址
udphead[3] = udpDestination[2] + udpDestination[3];
return true;
} //ip正则校验
private bool IsIP(string ip)
{ //判断是否为IP,加上是否有划分校验(/[012]?d|3[0-2])?
return Regex.IsMatch(ip, @"^((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?(/[012]?d|/3[0-2])?)$");
} //递归计算UDP头部所有十六进制数的和
private string CacuSum(string a, int i)
{
string tmp = TwoSum(a, udphead[i]);
if (i + 1 == 14)
{
allSum = tmp;
return tmp;
}
CacuSum(tmp, i + 1);
return "";
} //计算两个十六进制数的和
private string TwoSum(string a, string b)
{
int aint = 0, bint = 0;
int flag = a.Length;
for (int i = 0; i < a.Length; i++)
{
flag--;
aint += JudgeLoc(a[i]) * Convert.ToInt32(Math.Pow(16, flag));
}
flag = b.Length;
for (int i = 0; i < b.Length; i++)
{
flag--;
bint += JudgeLoc(b[i]) * Convert.ToInt32(Math.Pow(16, flag));
}
string Sum = Convert.ToString(aint + bint, 16).PadLeft(4, '0'); //存和的十六进制
return Sum;
} //计算十六进制字符对应的整型值
private int JudgeLoc(char c)
{
if (c > '0' && c <= '9')
{
return c - '0';
}
else if (c >= 'a' && c <= 'f')
{
return c - 'a' + 10;
}
return 0;
} //十六进制转二进制并进行取反操作
private string ConvertHexToBin(string hex)
{
int aint = 0;
int flag = hex.Length;
for (int i = 0; i < hex.Length; i++)
{
flag--; //调用十六进制转二进制的函数JudgeLoc
aint += JudgeLoc(hex[i]) * Convert.ToInt32(Math.Pow(16, flag));
}
string bina = Convert.ToString(aint, 2).PadLeft(16, '0'); //十六进制转二进制部分的代码 //二进制按位取反
string confBina = "";
for (int i = 0; i < bina.Length; i++)
{
char sigBina = bina[i];
if (sigBina == '0')
{
sigBina = '1';
}
else
{
sigBina = '0';
}
confBina += sigBina;
}
return confBina;
}
private string Cumulativesum(string hex)
{
int aint = 0;
int flag = hex.Length;
for (int i = 0; i < hex.Length; i++)
{
flag--;
aint += JudgeLoc(hex[i]) * Convert.ToInt32(Math.Pow(16, flag));
}
string bina = Convert.ToString(aint, 2).PadLeft(16, '0');
return bina;
}
private void Button2_Click(object sender, EventArgs e) //校验和转换为十六进制
{
if (!InfoCheck())
{
return;
}
udphead[9] = "0000";
CacuSum(udphead[0], 1);
string overflow = "";
if (allSum.Length > 4) //溢出处理
{
for (int i = 0; i < allSum.Length - 4; i++)
{
overflow += allSum[i];
}
}
allSum = allSum.Remove(0, allSum.Length - 4);
string checksum = ConvertHexToBin(TwoSum(overflow, allSum));
checksum = "0x" + string.Format("{0:x}", Convert.ToInt32(checksum, 2)).PadLeft(4, '0');
textBox15.Text = checksum; //校验和所在的框体
}
private void Button3_Click(object sender, EventArgs e) //UDP包的设计和实现发送模块
{
Form2 form2 = new Form2();
form2.Show();
}
private void Button4_Click(object sender, EventArgs e)
{ //新建文件
FileStream file = new FileStream("d:/IP_Information.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
StreamWriter writer = new StreamWriter(file, Encoding.UTF8); //中文乱码的解决办法
writer.WriteLine(
label2.Text + "n"
+ textBox2.Text + "