ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据


文章目录

  • 一、控制台程序使用UDP通信
    • 1.创建新项目
    • 2.编写代码
  • 二、Form窗口程序使用 TCP 通信
    • 1.创建新项目
    • 2.设计图形界面
    • 3.编写代码
    • 4.编译客户端和服务器端
  • 三、TCP编程-端口扫描器
    • 1.创建新项目
    • 2.设置界面
    • 3.编写代码
  • 四、总结
  • 五、参考链接

一、控制台程序使用UDP通信 1.创建新项目 (1)打开visual studio 2019,创建新项目
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(2)选择控制台应用(.net.Framework)
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(3)编辑项目名称,选择保存位置。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(4)创建好项目如下图所示
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

2.编写代码 在控制台上简单输出:
在 Main 函数内书写如下的代码(功能:连续输出 50 行数据)
for(int i = 0; i < 50; i++) { Console.WriteLine("第{0}行:hello cqjtu!重交物联2019级", (i + 1)); } System.Console.ReadKey();

编译运行结果:
使用UDP通信
(1)目前最普遍的服务模式是 C/S 模式,所以需要一个客户端 client 和一个服务端 Server ,来实现通信。
(2)比如我现在在我的电脑上运行一个客户端代码,在我室友的电脑上运行一个服务端的代码,就可以实现通信功能。
(3)在我自己的电脑上使用 VS2019 创建一个新项目 client ,并将下列代码复制粘贴进去。(注意头文件!!!使用网络协议需要引入头文件 .Net 和 .Net.Sockets)
客户端
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; namespace Client { class Program { static void Main(string[] args) { //提示信息 Console.WriteLine("按下任意按键开始发送..."); Console.ReadKey(); int m; //做好链接准备 UdpClient client = new UdpClient(); //实例一个端口 IPAddress remoteIP = IPAddress.Parse("192.168.43.15"); //假设发送给这个IP int remotePort = 11000; //设置端口号 IPEndPoint remotePoint = new IPEndPoint(remoteIP, remotePort); //实例化一个远程端点 for (int i = 0; i < 50; i++) { //要发送的数据:第n行:hello cqjtu!重交物联2018级 string sendString = null; sendString += "第"; m = i + 1; sendString += m.ToString(); sendString += "行:hello cqjtu!重交物联2019级"; //定义发送的字节数组 //将字符串转化为字节并存储到字节数组中 byte[] sendData = https://www.it610.com/article/null; sendData = Encoding.Default.GetBytes(sendString); client.Send(sendData, sendData.Length, remotePoint); //将数据发送到远程端点 } client.Close(); //关闭连接//提示信息 Console.WriteLine(""); Console.WriteLine("数据发送成功,按任意键退出..."); System.Console.ReadKey(); } } }

流程:
(1)首先显示提示信息,等待使用人员操作
(2)做好连接准备,如:设置IP地址,端口号
(3)for循环发送数据
(4)关闭端口
(5)显示提示信息,等待用户确认退出
在我室友的电脑上使用 VS2019 创建一个新项目 server,并将下列代码复制粘贴进去。
服务器端
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; namespace Server1 { class Program { static void Main(string[] args) { int result; string str = "第50行:hello cqjtu!重交物联2019级"; UdpClient client = new UdpClient(11000); string receiveString = null; byte[] receiveData = https://www.it610.com/article/null; //实例化一个远程端点,IP和端口可以随意指定,等调用client.Receive(ref remotePoint)时会将该端点改成真正发送端端点 IPEndPoint remotePoint = new IPEndPoint(IPAddress.Any, 0); Console.WriteLine("正在准备接收数据..."); while (true) { receiveData = https://www.it610.com/article/client.Receive(ref remotePoint); //接收数据 receiveString = Encoding.Default.GetString(receiveData); Console.WriteLine(receiveString); result = String.Compare(receiveString, str); if (result == 0) { break; } } client.Close(); //关闭连接 Console.WriteLine(""); Console.WriteLine("数据接收完毕,按任意键退出..."); System.Console.ReadKey(); } } }

代码流程:
①做好连接准备,并设置结束标志;
②循环接收数据;
③关闭连接;
④显示提示信息,等待用户确定退出。
运行结果显示
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(1)打开wirshark,点击捕获—>选项ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(2)选择WLAN,开始
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(3)可以看到现在 Wireshark 不断的在抓包,先点击红色的按钮暂停抓包。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(4)重新编译客户端和服务器端,先不要按下按键发送数据,先挂着,看下一步。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(5)点击鲨鱼鱼鳍的图标,然后点击 “ 继续不保存 ”,不保存之前抓取的包。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(6)然后按键盘开始发送数据,发送完后,点击 Wireshark 的红色按钮,停止抓包。
二、Form窗口程序使用 TCP 通信 1.创建新项目 (1)选中 “ Windows 窗体应用 ” ,再点击 “ 下一步 ”。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(2)设置项目名称、保存位置,再点击 “ 创建 ” 。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(3)创建完毕。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

2.设计图形界面 【ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据】摆放控件:
(1)首先往图形界面内拖动控件并进行摆放,如下图所示。
从工具箱内拖 2 个 TextBox 和 1 个 Button 控件。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

设置消息输入框属性:
(2)左键选中最下面的 TextBox ,并在右下角的属性中找到 Font 属性,并点击 “ … ”
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(3)然后在设计属性中的(Name)这里默认的 textBox1 ,也可以更改,但不能重复,唯一标识,这是控件的编号,用于代码编写的时候识别,就像是身份证号一样,不能出现中文。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(4)在布局这里,Location 是指控件左上角顶点基于窗口所在的位置,Size 是指控件的长和宽,可以自行设置。
也可自行拖动文本框,改变长宽,位置。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

(5)选中TextBox2
添加垂直滚动条:找到 ScrollBars 属性,设置参数为 Vertical
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

设置边界样式:找到 BorderStyle ,参数设置为 FixedSingle
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

编号为 textBox2 。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

设置消息显示界面的 TextBox 不可编辑:找到 Enabled 属性,参数设为 False 。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

设置发送消息按钮属性:
左键点击选中按钮,找到 Text 属性,参数输入为 “ 发送 ” ,则控件上就会显示输入的字样
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

它的唯一标识为:button1
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

设置窗体属性:
(1)左击窗体选中它,在右下角的属性中找到 Text 属性,编辑为 “ 客户端 ” ,然后窗体的左上角,就显示为 “ 客户端 ”。
(2)紧接着,有个 AcceptButton 属性,下拉框选中这个 button1 按钮,设置完这个属性后,当我们最后执行这个程序后,按下回车键 = 点击这个按钮。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

至此,控件的一些简单属性就设置完毕了。
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

3.编写代码
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 = 82569; string host = "192.168.43.14"; //我室友的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 = ""; } } }

**流程:
当点击按钮后,button1_Click 函数开始执行。
①获取当前时间,并打印到消息显示界面内;
②做连接服务器端的准备,如:设置IP、设置端口号、实例socket端口;
③打印连接信息,并连接服务器;
④从消息输入框获取字符串并按照UTF8编码到字节数组存储,然后发送出去。
⑤将从服务器端接收到的字节流按照UTF8解码为字符串并存储打印出来。
⑥关闭socket端口变量。
两个 catch 是做异常情况处理,并打印到消息显示界面内。
接下来开始编写服务器端代码:
注:从第三部分: “ Form窗口程序使用 TCP 通信 ” 开始至此,都是在编写客户端的部分,接下来我们需要编写服务器端的代码了。
根据第二部分: “ 控制台程序使用 UDP 通信 ” 创建一个新的控制台程序,这里就不再演示了。
复制下面 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 = 82569; string host = "192.168.43.14"; 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.编译客户端和服务器端 客户端
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

服务器端:
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

现在向服务器发送数据
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

服务器端
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

三、TCP编程-端口扫描器 1.创建新项目 ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

2.设置界面 需要1个button,1个Listbox,4个TextBox,5个label控件
ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

3.编写代码 单线程
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp3 { public partial class Form1 : Form { //主机地址 private string hostAddress; //起始端口 private int start; //终止端口 private int end; //端口号 private int port; //定义线程对象 //private Thread scanThread; public Form1() { InitializeComponent(); }private void label1_Click(object sender, EventArgs e) {}private void label3_Click(object sender, EventArgs e) { }private void button1_Click(object sender, EventArgs e) { try {//初始化 textBox4.Clear(); label5.Text = "0%"; //获取ip地址和始末端口号 hostAddress = textBox1.Text; start = Int32.Parse(textBox2.Text); end = Int32.Parse(textBox3.Text); if (decideAddress()) { //让输入的textbox只读,无法改变 textBox1.ReadOnly = true; textBox2.ReadOnly = true; textBox3.ReadOnly = true; //设置进度条的范围 progressBar1.Minimum = start; progressBar1.Maximum = end; //显示框显示 textBox4.AppendText("端口扫描器 v1.0.0" + Environment.NewLine + Environment.NewLine); //调用端口扫描函数 PortScan(); } else { //若端口号不合理,弹窗报错 MessageBox.Show("输入错误,端口范围为[0-65536]!"); } } catch { //若输入的端口号为非整型,则弹窗报错 MessageBox.Show("输入错误,端口范围为[0-65536]!"); } }private bool decideAddress() { //判断端口号是否合理 if ((start >= 0 && start <= 65536) && (end >= 0 && end <= 65536) && (start <= end)) return true; else return false; }private void PortScan() { double x; string xian; //显示扫描状态 textBox4.AppendText("开始扫描...(可能需要请您等待几分钟)" + Environment.NewLine + Environment.NewLine); //循环抛出线程扫描端口 for (int i = start; i <= end; i++) { x = (double)(i - start + 1) / (end - start + 1); xian = x.ToString("0%"); port = i; //调用端口i的扫描操作 Scan(); //进度条值改变 label5.Text = xian; label5.Refresh(); progressBar1.Value = https://www.it610.com/article/i; } textBox1.AppendText(Environment.NewLine +"扫描结束!" + Environment.NewLine); //输入框textbox只读属性取消 textBox1.ReadOnly = false; textBox2.ReadOnly = false; textBox3.ReadOnly = false; }private void Scan() { int portnow = port; //创建TcpClient对象,TcpClient用于为TCP网络服务提供客户端连接 TcpClient objTCP = null; try { //用于TcpClient对象扫描端口 objTCP = new TcpClient(hostAddress, portnow); //扫描到则显示到显示框 textBox1.AppendText("端口 " + port + " 开放!" + Environment.NewLine); } catch { //未扫描到,则会抛出错误 } } } }

ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

多线程
代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using System.Windows.Forms; using System.Threading; namespace WindowsFormsApp4 { public partial class Form1 : Form { //主机地址 private string hostAddress; //起始端口 private int start; //终止端口 private int end; //端口号 private int port; //定义线程对象 private Thread scanThread; //定义端口状态数据(开放则为true,否则为false) private bool[] done = new bool[65526]; private bool OK; public Form1() { InitializeComponent(); //不进行跨线程检查 CheckForIllegalCrossThreadCalls = false; }private void textBox4_TextChanged(object sender, EventArgs e) {}private void progressBar1_Click(object sender, EventArgs e) {}private void button1_Click(object sender, EventArgs e) { try { //初始化 textBox4.Clear(); label5.Text = "0%"; //获取ip地址和始末端口号 hostAddress = textBox1.Text; start = Int32.Parse(textBox2.Text); end = Int32.Parse(textBox3.Text); if (decideAddress()) { textBox1.ReadOnly = true; textBox2.ReadOnly = true; textBox3.ReadOnly = true; //创建线程,并创建ThreadStart委托对象 Thread process = new Thread(new ThreadStart(PortScan)); process.Start(); //设置进度条的范围 progressBar1.Minimum = start; progressBar1.Maximum = end; //显示框显示 textBox4.AppendText("端口扫描器 v1.0.0" + Environment.NewLine + Environment.NewLine); } else { //若端口号不合理,弹窗报错 MessageBox.Show("输入错误,端口范围为[0-65536]!"); } } catch { //若输入的端口号为非整型,则弹窗报错 MessageBox.Show("输入错误,端口范围为[0-65536]!"); } }private bool decideAddress() { //判断端口号是否合理 if ((start >= 0 && start <= 65536) && (end >= 0 && end <= 65536) && (start <= end)) return true; else return false; }private void PortScan() { double x; string xian; //显示扫描状态 textBox4.AppendText("开始扫描...(可能需要请您等待几分钟)" + Environment.NewLine + Environment.NewLine); //循环抛出线程扫描端口 for (int i = start; i <= end; i++) { x = (double)(i - start + 1) / (end - start + 1); xian = x.ToString("0%"); port = i; //使用该端口的扫描线程 scanThread = new Thread(new ThreadStart(Scan)); scanThread.Start(); //使线程睡眠 System.Threading.Thread.Sleep(100); //进度条值改变 label5.Text = xian; progressBar1.Value = https://www.it610.com/article/i; } while (!OK) { OK = true; for (int i = start; i <= end; i++) { if (!done[i]) { OK = false; break; } } System.Threading.Thread.Sleep(1000); } textBox4.AppendText(Environment.NewLine +"扫描结束!" + Environment.NewLine); textBox1.ReadOnly = false; textBox2.ReadOnly = false; textBox3.ReadOnly = false; }private void Scan() { int portnow = port; //创建线程变量 Thread Threadnow = scanThread; //扫描端口,成功则写入信息 done[portnow] = true; //创建TcpClient对象,TcpClient用于为TCP网络服务提供客户端连接 TcpClient objTCP = null; try { //用于TcpClient对象扫描端口 objTCP = new TcpClient(hostAddress, portnow); //扫描到则显示到显示框 textBox4.AppendText("端口 " + port + " 开放!" + Environment.NewLine); } catch { //未扫描到,则会抛出错误 } } } }

ubuntu|C#使用TCP/UDP协议通信并用Wireshark抓包分析数据
文章图片

相比于单线程,多线程快很多
四、总结 本实验主要是用C#编写一个命令行/控制台的简单hello world程序,实现如下功能:在屏幕上连续输出50行“hello cqjtu!重交物联2019级”;同时打开一个网络UDP 套接字,向另一台室友电脑发送这50行消息。
用VS2019 的C#编写一个简单的Form窗口程序,有一个文本框 textEdit和一个发送按钮button,运行程序后,可以在文本框里输入文字,如“hello cqjtu!重交物联2019级”,点击button,将这些文字发送给室友电脑,采用UDP套接字;
编写端口扫描器程序,分别采用单一进程和多线程方式,对比两者的效果
五、参考链接 https://blog.csdn.net/ssj925319/article/details/109336123
https://blog.csdn.net/tyro_00/article/details/109827571
https://blog.csdn.net/qq_55691662/article/details/121455003?spm=1001.2014.3001.5501

    推荐阅读