WPF制作的实现Socket通讯中UDP协议的例子

这是学习Socket制作的,是两个项目,分别为客户端和服务器端,在测试的时候需要同时运行起来。

UDP一般和TCP协议进行比较,具体不同可百度大神的文章学习。根据我的理解,UDP协议中最重要的两个方法是ReceiveFrom()和SendTo(), “UDP应用上已经无严格意义上的真正的服务器和客户端之分了”,其实就是通过IP地址和端口进行数据的发送和接收。

在学习的过程中碰到了几个难点:

1、无论是服务端和客户端在接收信息的时候,设置缓存区接收信息如下

 byte[] data = new byte[1024];
 recv= SocClient.ReceiveFrom(data, ref RemotePoint);
 this.Dispatcher.Invoke(new Action(() => { tblock_message.Text += (RemotePoint.ToString()+Encoding.Default.GetString(data,0,recv)); }));             

如果设置的读取信息语句如下,

Encoding.Default.GetString(data)

则文本框上就会将data中1204个字节都显示出来,很影响效果,所以改成

Encoding.Default.GetString(data,0,recv)

则显示的正常。

2、由于接收信息的是个单独的线程,如果给主界面上的文本框中添加文字,则会提示“调用线程无法访问此对象,因为另一个线程拥有该对象”,所以设置如下语句进行解决:

     this.Dispatcher.Invoke(new Action(() => { tblock_message.Text += (RemotePoint.ToString()+Encoding.Default.GetString(data,0,recv)); }));


下面贴出代码:

服务端 前端:

<Window x:Class="UdpServe.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:UdpServe"
        mc:Ignorable="d"
        Title="服务器端" Height="375" Width="524">
    <Grid>
        <Button Name="btn_send" Content="发送信息" HorizontalAlignment="Left" Margin="333,244,0,0" VerticalAlignment="Top" Width="75" Click="btn_send_Click" />
        <TextBox  Name="tblock_message" ScrollViewer.VerticalScrollBarVisibility="Auto" Background="Cornsilk"  HorizontalAlignment="Left" Margin="34,10,0,0"  VerticalAlignment="Top" Height="208" Width="464"/>
        <Button Name="btn_connect" Content="开启服务" HorizontalAlignment="Left" Margin="243,244,0,0" VerticalAlignment="Top" Width="75" Click="btn_connect_Click"/>
        <Label Content="IP地址" HorizontalAlignment="Left" Margin="33,269,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="tb_Ip"  HorizontalAlignment="Left" Height="23" Margin="91,272,0,0"  VerticalAlignment="Top" Width="136" Text="0.0.0.0" IsEnabled="False"/>
        <Button Name="btn_clear" Content="清屏" HorizontalAlignment="Left" Margin="424,244,0,0" VerticalAlignment="Top" Width="75" Click="btn_clear_Click" />
        <Label Content="昵称" HorizontalAlignment="Left" Margin="33,241,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="tb_ServeName"  HorizontalAlignment="Left" Height="23" Margin="91,244,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="136" Text="阿森纳"/>
        <Label Content="端口" HorizontalAlignment="Left" Margin="33,301,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="tb_Port"  HorizontalAlignment="Left" Height="23" Margin="91,304,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="136" Text="8080"/>
        <TextBox x:Name="tb_message"  HorizontalAlignment="Left" Height="54" Margin="243,273,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="255"/>
    </Grid>
</Window>

服务端 后端:

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

namespace UdpServe
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            tb_Ip.Text = getIPAddress();
        }

        private IPEndPoint ipLocalPoint;
        private EndPoint RemotePoint;
        private Socket mySocket;

        /// <summary>
        /// 获得本机局域网IP地址  
        /// </summary>   
        private string getIPAddress()
        {           
            string HostName = Dns.GetHostName();
            IPAddress[] AddressList = Dns.GetHostByName(HostName).AddressList;
            if (AddressList.Length < 1)
            {
                return "";
            }
            return AddressList[0].ToString();
        }


        /// <summary>
        /// 服务端监听
        /// </summary>
        private void serverListen()
        {
            try
            {
                //与 address 关联的端口号,或为 0 以指定任何可用端口。port 以主机顺序排列。
                IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
                RemotePoint = (EndPoint)(sender);
                int recv;

                //启动一个新的线程,执行方法this.ReceiveHandle,以便在一个独立的进程中执行数据接收的操作  
                while (true)
                {
                    byte[] data = new byte[1024];
                    recv= mySocket.ReceiveFrom(data, ref RemotePoint);   
                    this.Dispatcher.Invoke(new Action(() => { tblock_message.Text += (RemotePoint.ToString()+Encoding.Default.GetString(data,0,recv)); }));
                }
            }
            catch (Exception ex)
            {
                this.Dispatcher.Invoke(new Action(() => { tblock_message.Text += ex.Message + "\n"; }));
            }            
        }

        /// <summary>
        /// 建立连接
        /// </summary>
        private void btn_connect_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                //定义网络类型,数据连接类型和网络协议UDP  
                mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                ipLocalPoint = new IPEndPoint(IPAddress.Parse(tb_Ip.Text), int.Parse(tb_Port.Text));
                mySocket.Bind(ipLocalPoint);

                Thread thread = new Thread(new ThreadStart(serverListen));
                thread.IsBackground = true;
                thread.Start();
                tblock_message.Text += "服务器建立连接" + "\n";
            }
            catch (Exception ex)
            {
                tblock_message.Text += ex.Message + "\n";
            }
        }


        /// <summary>
        /// 发送信息
        /// </summary>
        private void btn_send_Click(object sender, RoutedEventArgs e)
        {
            try
            {      
                byte[] mess = Encoding.Default.GetBytes(tb_ServeName.Text + ":" + tb_message.Text+"\n");
                mySocket.SendTo(mess, mess.Length, SocketFlags.None, RemotePoint);
                tblock_message.Text += Encoding.Default.GetString(mess);
            }
            catch (Exception ex)
            {
                tblock_message.Text += ex.Message+ "\n";       
            }
        }

        private void btn_clear_Click(object sender, RoutedEventArgs e)
        {
            tblock_message.Text = "";
        }
    }
}

客户端 前端:

<Window x:Class="UdpClient.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:UdpClient"
        mc:Ignorable="d"
        Title="我是客户端之1号机" Height="375" Width="524">
    <Grid>
        <Button Name="btn_send" Content="发送信息" HorizontalAlignment="Left" Margin="333,244,0,0" VerticalAlignment="Top" Width="75" Click="btn_send_Click" />
        <TextBox  Name="tblock_message" ScrollViewer.VerticalScrollBarVisibility="Visible"  Background="Cornsilk"  HorizontalAlignment="Left" Margin="34,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="208" Width="464"/>
        <Button Name="btn_connect" Content="开启服务" HorizontalAlignment="Left" Margin="243,244,0,0" VerticalAlignment="Top" Width="75" Click="btn_connect_Click"/>
        <Label Content="IP地址" HorizontalAlignment="Left" Margin="33,269,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="tb_Ip"  HorizontalAlignment="Left" Height="23" Margin="91,272,0,0"  VerticalAlignment="Top" Width="136" Text="0.0.0.0" IsEnabled="False"/>
        <Button Name="btn_clear" Content="清屏" HorizontalAlignment="Left" Margin="424,244,0,0" VerticalAlignment="Top" Width="75" Click="btn_clear_Click" />
        <Label Content="昵称" HorizontalAlignment="Left" Margin="33,241,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="tb_ServeName"  HorizontalAlignment="Left" Height="23" Margin="91,244,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="136" Text="利物浦"/>
        <Label Content="端口" HorizontalAlignment="Left" Margin="33,301,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="tb_Port"  HorizontalAlignment="Left" Height="23" Margin="91,304,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="136" Text="8090"/>
        <TextBox x:Name="tb_message"  HorizontalAlignment="Left" Height="54" Margin="243,273,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="255"/>
    </Grid>
</Window>

客户端 后端:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace UdpClient
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        Socket SocClient;
        IPEndPoint IpClient;  
         EndPoint RemotePoint;
        IPEndPoint IpServe;

        /// <summary>
        /// 建立连接
        /// </summary>
        private void btn_connect_Click(object sender, RoutedEventArgs e)
        {
            try
            {  
                //定义网络类型,数据连接类型和网络协议UDP  
                SocClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                //设置服务IP,设置UDP端口号
                IpClient = new IPEndPoint(IPAddress.Parse(tb_Ip.Text), int.Parse(tb_Port.Text));
                SocClient.Bind(IpClient);

                Thread thread = new Thread(new ThreadStart(serverListen));
                thread.IsBackground = false;
                thread.Start();
                tblock_message.Text += "客户端建立连接" + "\n";
            }
            catch (Exception ex)
            {
                tblock_message.Text += ex.Message + "\n";
            }
        }

        private void serverListen()
        {
            try
            {
                //得到服务器IP 
                //与 address 关联的端口号,或为 0 以指定任何可用端口。port 以主机顺序排列。
                IpServe = new IPEndPoint(IPAddress.Parse("192.168.0.114"), 8080);
                RemotePoint = (EndPoint)(IpServe);

                int recv;
                //启动一个新的线程,执行方法this.ReceiveHandle,以便在一个独立的进程中执行数据接收的操作  
                while (true)
                {
                    byte[] data = new byte[1024];
                    recv= SocClient.ReceiveFrom(data, ref RemotePoint);
                    this.Dispatcher.Invoke(new Action(() => { tblock_message.Text += (RemotePoint.ToString()+Encoding.Default.GetString(data,0,recv)); }));             
                }
            }
            catch (Exception ex)
            {
                this.Dispatcher.Invoke(new Action(() => { tblock_message.Text += ex.Message + "\n"; }));
            }    
        }

        private void btn_send_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                byte[] mess = Encoding.Default.GetBytes(tb_ServeName.Text + ":" + tb_message.Text + "\n");
                SocClient.SendTo(mess, mess.Length, SocketFlags.None, RemotePoint);
                tblock_message.Text += Encoding.Default.GetString(mess);
            }
            catch (Exception ex)
            {
                tblock_message.Text += ex.Message + "\n";               
            }
        }

        private void btn_clear_Click(object sender, RoutedEventArgs e)
        {
            tblock_message.Text = "";         
        }
    }
}




猜你喜欢

转载自blog.csdn.net/weixin_40825039/article/details/80167589