C#控制台编程及网络编程入门

本文介绍了C#中使用UDP进行简单通信的实例,包括服务端和客户端的创建,并展示了如何在VS2019中构建一个简单的Form窗口程序,用于UDP数据收发。此外,还探讨了使用Wireshark进行网络封包分析的基本步骤,强调了UDP协议在速度和消息边界方面的优势,以及在不可靠传输和无序传输的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 UDP编程

UDP和TCP的区别
UDP和TCP的主要区别在是二者在如何实现信息的可靠传递方面存在不同,具体表现为以下几点:
▼UDP可靠性不如TCP
TCP包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传递其他消息,否则将一直等待,直到收到确认信息为止。与TCP不同,UDP并不提供数据传达的保证机制。如果在发送方到接收方的传递过程中出现数据包的丢失,协议本身并不能做出任何检测或提示。因此人们把UDP称为不可靠的传输协议。
▼UDP不能保证有序传输
UDP不能确保数据的发送和接收顺序。对于突发性的数据报,有可能会乱序。不过,事实上UDP的这种乱序基本上很少出现,通常只会在网络非常拥挤的情况下才有可能发生。


说了这么多UDP的缺点,那使用它还有什么价值么?
从应用角度考虑,UDP相比TCP的优势,主要表现在以下几个方面。
UDP速度比TCP要快
UDP有消息边界
UDP可以一对多传输

1、简单的C#控制台应用

使用VS2019 完成第一个C#程序,显示多行输出。
1.1 文件—>新建项目,选择C#,控制台。然后下一步
在这里插入图片描述
1.2 更改项目名字及位置,然后创建
在这里插入图片描述
1.3 进入程序编写
在这里插入图片描述
代码内容

for(int i=0;i<50;i++)          //for循环,小于五十次就继续输出内容
Console.WriteLine("Hello World,Hello C#");//显示输出输出内容
Console.ReadKey();            //暂停程序,按下任意键继续

1.4运行结果
在这里插入图片描述
这样,入门C#控制台程序就完成了。

2、C#使用UdpClient类进行简单通信

2.1、创建一个控制台程序:服务端,步骤和前面一样。
代码如下:

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

namespace ConsoleApp2
{/// <summary>
 /// 服务端
 /// </summary>
    class UDPReceive
    {
        static void Main(string[] args)
        {
            //创建一个UdpClient对象,11000为接收端口
            UdpClient udpReceive = new UdpClient(11000);

            //设置远程主机,(IPAddress.Any, 0)代表接收所有IP所有端口发送的数据
            IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);//或 IPEndPoint remoteIpEndPoint = null;
int i = 0;

            while (true)
            {
                //监听数据,接收到数据后,把数据转换成字符串并输出
                byte[] receiveBytes = udpReceive.Receive(ref remoteIpEndPoint);

                string returnData = Encoding.UTF8.GetString(receiveBytes);

                Console.WriteLine(++i +  returnData.ToString());
            }
                udpReceive.Close();
        }
    }
}

在这里插入图片描述

2.2、新建一个控制台程序:客服端
代码如下

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


namespace ConsoleApp1
{
    /// <summary>
    /// 客户端
    /// </summary>
    class UDPSender
    {
        static void Main(string[] args)
        {
            //创建一个UdpClient对象,0表示系统自动分配发送端口
            //(若同时在本机运行服务端和客户端,则服务端接收和客户端发送需要使用不同端口,否则两个程序使用同一端口将引发冲突)
            UdpClient udpSender = new UdpClient(0);

            //连接到服务端并指定接收端口
            udpSender.Connect("localhost", 11000);

            //连接到子网广播地址并指定接收端口
            //udpSender.Connect("192.168.1.255", 11000);
            //(在使用TCP/IP协议的网络中,主机标识段全为1的IP地址为广播地址,广播地址传送给主机标识段所涉及的所有计算机。
            //例如,对于192.168.1.0(255.255.255.0)网段,其广播地址为192.168.1.255(255的2进制即为11111111),
            //当发出目的地址为192.168.1.255时,它将分发给该网段上的所有计算机。)

            //把消息转换成字节流发送到服务端
            byte[] sendBytes = Encoding.UTF8.GetBytes("Hello World,Hello C#");

            string a;
            a = Console.ReadLine();     //从控制台获取数据
            for (int i = 0; i < 50; i++)  //循环,客户端发送一条消息,服务端收到50条
            {
                udpSender.Send(Encoding.UTF8.GetBytes(a), Encoding.UTF8.GetBytes(a).Length);
                //把发送内容转换成字节流,以及发送的字节长度
            }
            //关闭链接
            udpSender.Close();


        }
    }
}

在这里插入图片描述
2.3、运行程序

需要先运行服务端,再运行客户端。否则客户端在服务端运行之前就已经发出数据,则服务端不会接收到数据。

▼客户端输入:
在这里插入图片描述
▼服务端接收:
在这里插入图片描述

这里是本机的客户端和服务端的连接,也可以连接其他电脑和设备。基本就更改一下IP地址,有需要的就关掉防火墙。

Scoket UDP编程的流程图
在这里插入图片描述

二、用C#编写一个简单的Form窗口程序

1、用VS2019建立一个窗口程序项目

▼文件—>新建项目在这里插入图片描述

2、窗体设计

▼在视图—>工具箱中调出控件
在这里插入图片描述
▼拖动按钮进行布局
在这里插入图片描述
▼点击控件,右下角可以更改name
在这里插入图片描述

3、代码编写

▼在同一台电脑测试时所用的代码:

using System;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private UdpClient receiveUdpClient;//接收用
        private UdpClient sendUdpClient;//发送用
        private const int port = 8001;//和本机绑定的端口号
        IPAddress ip;//本机ip
        IPAddress remoteip;//远程主机ip
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            //获取本机可用IP地址
            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
            foreach (IPAddress ipa in ips)
            {
                if (ipa.AddressFamily == AddressFamily.InterNetwork)
                {
                    ip = ipa;
                    break;
                }
            }

            //为了在同一台机器调试,此IP也作为默认远程IP
            remoteip = ip;
            //IPAddress remoteip = IPAddress.Parse("");   

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //创建一个线程接收远程主机发来的信息
            Thread myThread = new Thread(ReceiveData);
            myThread.IsBackground = true;
            myThread.Start();
        }

        //接收数据
        private void ReceiveData()
        {
            IPEndPoint local = new IPEndPoint(ip, port);
            receiveUdpClient = new UdpClient(local);
            IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);
            while (true)
            {
                try
                {
                    //关闭udpClient 时此句会产生异常
                    byte[] receiveBytes = receiveUdpClient.Receive(ref remote);
                    string receiveMessage = Encoding.Unicode.GetString(
                        receiveBytes, 0, receiveBytes.Length);
                    listBox1.Items.Add("收到的消息:" + receiveMessage);
                }
                catch
                {
                    break;
                }
            }
        }
        //点击发送按钮发送数据

        private void button1_Click_1(object sender, EventArgs e)
        {
            //remoteip = IPAddress.Parse(txt_IPAddress.Text);
            Thread myThread = new Thread(SendMessage);
            myThread.IsBackground = true;
            myThread.Start(textBox1.Text);
        }
        //发送消息
        private void SendMessage(object obj)
        {
            string message = (string)obj;
            sendUdpClient = new UdpClient(0);
            byte[] bytes = Encoding.UTF8.GetBytes(message);
            IPEndPoint iep = new IPEndPoint(remoteip, port);
            try
            {
                sendUdpClient.Send(bytes, bytes.Length, iep);
                listBox1.Items.Add("发送的消息:" + message);
                textBox1.Clear();
            }
            catch (Exception ex)
            {
                listBox1.Items.Add("发送出错:" + ex.Message);
            }
        }
        delegate void AddItemDelegate(ListBox listbox, string text);
        private void AddItem(ListBox listbox, string text)
        {
            if (listbox.InvokeRequired)
            {
                AddItemDelegate d = AddItem;
                //Control.Invoke 方法 (Delegate, Object[]):
                //在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。
                listbox.Invoke(d, new object[] { listbox, text });
            }
            else
            {
                //Add:动态的添加列表框中的项
                listbox.Items.Add(text);

                //SelectedIndex属性获取单项选择ListBox中当前选定项的位置
                //Count:列表框中条目的总数
                listbox.SelectedIndex = listbox.Items.Count - 1;

                //调用此方法等效于将 SelectedIndex 属性设置为-1。 
                //可以使用此方法快速取消选择列表中的所有项。
                listbox.ClearSelected();
            }
        }
        delegate void ClearTextBoxDelegate();
        private void ClearTextBox()
        {
            if (textBox1.InvokeRequired)
            {
                ClearTextBoxDelegate d = ClearTextBox;
                textBox1.Invoke(d);
            }
            else
            {
                textBox1.Clear();
                textBox1.Focus();
            }
        }

        private void button2_Click_1(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

这里提示一下🙄,如图如果这种些地方是“0引用”,那个就是这个控件的功能没有激活。需要到设计界面去双击相应的控件,激活后然后编写控制代码

在这里插入图片描述
▼不同电脑间通信程序代码

using System;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private UdpClient receiveUdpClient;//接收用
        private UdpClient sendUdpClient;//发送用
        private const int port = 10000;//和本机绑定的端口号
        IPAddress ip = IPAddress.Parse("10.60.191.8");//本机ip
        IPAddress remoteip = IPAddress.Parse("10.60.191.43");//远程主机ip
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
            ////获取本机可用IP地址
            //IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
            //foreach (IPAddress ipa in ips)
            //{
            //    if (ipa.AddressFamily == AddressFamily.InterNetwork)
            //    {
            //        ip = ipa;
            //        break;
            //    }
            //}

            //为了在同一台机器调试,此IP也作为默认远程IP.

           //- remoteip = ip;
            //IPAddress remoteip = IPAddress.Parse("");   

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //创建一个线程接收远程主机发来的信息
            Thread myThread = new Thread(ReceiveData);
            myThread.IsBackground = true;
            myThread.Start();
        }

        //接收数据
        private void ReceiveData()
        {
            IPEndPoint local = new IPEndPoint(ip, port);
            receiveUdpClient = new UdpClient(local);
            IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);
            while (true)
            {
                try
                {
                    //关闭udpClient 时此句会产生异常
                    byte[] receiveBytes = receiveUdpClient.Receive(ref remote);
                    string receiveMessage = Encoding.UTF8.GetString(
                        receiveBytes, 0, receiveBytes.Length);
                    listBox1.Items.Add("收到的消息:" + receiveMessage);
                }
                catch
                {
                    break;
                }
            }
        }
        //点击发送按钮发送数据

        private void button1_Click_1(object sender, EventArgs e)
        {
            //remoteip = IPAddress.Parse(txt_IPAddress.Text);
            Thread myThread = new Thread(SendMessage);
            myThread.IsBackground = true;
            myThread.Start(textBox1.Text);
        }
        //发送消息
        private void SendMessage(object obj)
        {
            string message = (string)obj;
            sendUdpClient = new UdpClient(0);
            byte[] bytes = Encoding.UTF8.GetBytes(message);
            IPEndPoint iep = new IPEndPoint(remoteip, port);
            try
            {
                sendUdpClient.Send(bytes, bytes.Length, iep);
                listBox1.Items.Add("发送的消息:" + message);
                textBox1.Clear();
            }
            catch (Exception ex)
            {
                listBox1.Items.Add("发送出错:" + ex.Message);
            }
        }
        delegate void AddItemDelegate(ListBox listbox, string text);
        private void AddItem(ListBox listbox, string text)
        {
            if (listbox.InvokeRequired)
            {
                AddItemDelegate d = AddItem;
                //Control.Invoke 方法 (Delegate, Object[]):
                //在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。
                listbox.Invoke(d, new object[] { listbox, text });
            }
            else
            {
                //Add:动态的添加列表框中的项
                listbox.Items.Add(text);

                //SelectedIndex属性获取单项选择ListBox中当前选定项的位置
                //Count:列表框中条目的总数
                listbox.SelectedIndex = listbox.Items.Count - 1;

                //调用此方法等效于将 SelectedIndex 属性设置为-1。 
                //可以使用此方法快速取消选择列表中的所有项。
                listbox.ClearSelected();
            }
        }
        delegate void ClearTextBoxDelegate();
        private void ClearTextBox()
        {
            if (textBox1.InvokeRequired)
            {
                ClearTextBoxDelegate d = ClearTextBox;
                textBox1.Invoke(d);
            }
            else
            {
                textBox1.Clear();
                textBox1.Focus();
            }
        }

        private void button2_Click_1(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

简单来说,两个代码就如下区别。其他的部分都一样
在这里插入图片描述

4、运行结果

▼本机运行结果
编辑内容,点击发送
在这里插入图片描述
接收到得内容在这里插入图片描述
▼两台电脑通信结果

三、wireshark抓包分析

1、安装并打开wireshark

运行程序与其他主机通信一下,然后进入找到刚刚通讯的IP号
在这里插入图片描述

2、帧的格式为: 前导码–>目的地址–>源地址–>协议类型–>数据包–>校核码,我们注重分析以下几个内容

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

四、参考资料

UDP协议与wireshark实验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值