C#与FX5U进行Socket通信

发布于:2025-07-14 ⋅ 阅读:(15) ⋅ 点赞:(0)

实现效果

实现步骤:

注意:详细的参数这里就不说明了,自己网上搜即可;

打开GX Works3 创建FX5U项目

系统参数设置PLC的具体型号(我有实物PLC)

设置IP及组态参数

添加通讯设备(这里PLC做客户端,因此添加:Active连接设备);

设置PLC的端口号、服务器IP、服务器端口号;

当前添加的设备No为1,记住这个参数,后面程序要输入;

配置完后点击应用并下载到PLC,下载完要重启PLC;

下面不废话,直接上PLC程序;

重点:

在线监控数据

监控D1300是通讯接收数据的起始地址,同时它还存储对方使用了多少个字节发送数据过来;那么我们要截取数据就要从D1301及以后开始截;

还看到PC只发了5个字符,但是收到却多了一位(发:SN123;收:SN1239);那么就要处理一下;把多余的字符删掉;

本项目案例把收到的数据又传回给PC;经过上面的处理已经拿到完整的数据了,然后置位一下M11就能把数据发给PC,注意每次发送都要触发一下M11,可以自己改成自动发送;

C#部分

创建一个页面 SocketPage.xaml

页面代码

<Page x:Class="WpfApp4.Views.SocketPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WpfApp4.Views"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="650"
      Title="SocketPage" >

    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="35"/>
            <RowDefinition Height="35"/>
            <RowDefinition Height="35"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Grid.Row="0">
            <Border Height="30" Width="100" Background="White">
                <TextBlock Text="状态显示"  FontSize="20"   VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/>
            </Border>
            <Border Height="30" Width="500" Background="#FF0ABEFF">
                <TextBlock Text="欢迎使用该软件" x:Name="txtb_serverData" FontSize="20"   VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/>
            </Border>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Grid.Row="1">
            <Border Height="30" Width="100" Background="White">
                <TextBlock Text="读取信息"  FontSize="20"   VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/>
            </Border>
            <Border Height="30" Width="500" Background="#FF0ABEFF">
                <TextBlock Text="------" x:Name="txtb_reData" FontSize="20"   VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/>
            </Border>
        </StackPanel>
        <StackPanel Orientation="Horizontal" Grid.Row="2">
            <Border Height="30" Width="100" Background="White">
                <TextBlock Text="连接设备"  FontSize="20"   VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/>
            </Border>
            <Border Height="30" Width="500" Background="#FF0ABEFF">
                <TextBlock Text="127.0.0.0:888" x:Name="txtb_ConnentDevice" FontSize="20"   VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/>
            </Border>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Grid.Row="3">
            <GroupBox Header="服务器与PLC通讯" Width="250" Height="150"  FontSize="20" BorderBrush="#FF0ABEFF" BorderThickness="2">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>

                    </Grid.RowDefinitions>
                    <StackPanel VerticalAlignment="Center"   Orientation="Horizontal"  Grid.Row="0">
                        <Border HorizontalAlignment="Left" >
                            <TextBlock Text="服务器IP: "   />
                        </Border>
                        <Border HorizontalAlignment="Right" >
                            <TextBox Text="192.168.2.223" x:Name="txb_ServerAdderess" VerticalAlignment="Center"  TextAlignment="Center" FontSize="16" Width="145"/>
                        </Border>
                    </StackPanel>

                    <StackPanel VerticalAlignment="Center"   Orientation="Horizontal"  Grid.Row="1">
                        <Border HorizontalAlignment="Left" >
                            <TextBlock Text="端口号: "   />
                        </Border>
                        <Border HorizontalAlignment="Right">
                            <TextBox Text="8000" x:Name="txb_Prot" Width="100" TextAlignment="Center"/>
                        </Border>
                    </StackPanel>

                    <Border Grid.Row="2" Width="150" Height="30">
                        <Button x:Name="btn_OpenConnent" Content="打开服务器"  Click="Button_OpenProtClick"/>
                    </Border>

                </Grid>
            </GroupBox>
            <GroupBox Header="写数据给PLC" Width="250" Height="150"  FontSize="20" BorderBrush="#FF0ABEFF" BorderThickness="2">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>

                    </Grid.RowDefinitions>
                    <StackPanel VerticalAlignment="Center"   Orientation="Horizontal"  Grid.Row="0">
                        <Border HorizontalAlignment="Left" >
                            <TextBlock Text="开   头: "   Width="70"/>
                        </Border>
                        <Border HorizontalAlignment="Right" >
                            <TextBox Text="SN" x:Name="txb_WriteSN" VerticalAlignment="Center"  TextAlignment="Center" FontSize="16" Width="145"/>
                        </Border>
                    </StackPanel>

                    <StackPanel VerticalAlignment="Center"   Orientation="Horizontal"  Grid.Row="1">
                        <Border HorizontalAlignment="Left" >
                            <TextBlock Text="序列号: "   Width="70"/>
                        </Border>
                        <Border HorizontalAlignment="Right">
                            <TextBox Text="123456789" x:Name="txb_WriteNume" Width="145" TextAlignment="Center" FontSize="16"/>
                        </Border>
                    </StackPanel>

                    <Border Grid.Row="2" Width="150" Height="30">
                        <Button x:Name="btn_WriteDevice" Content="写入"  Click="btn_WriteDevice_Click"/>
                    </Border>

                </Grid>
            </GroupBox>
        </StackPanel>

    </Grid>
</Page>

页面后台代码

using System;
using System.Collections.Generic;
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.Media;

namespace WpfApp4.Views
{
    /// <summary>
    /// SocketPage.xaml 的交互逻辑
    /// </summary>
    public partial class SocketPage : Page
    {
        public SocketPage()
        {
            InitializeComponent();


        }

        /// <summary>
        /// 打开/关闭连接
        /// </summary>
        bool isConnent = false;

        /// <summary>
        /// 服务器已创建
        /// </summary>
        bool isOpenConnent = false;

        /// <summary>
        /// 触发写入
        /// </summary>
        bool btn_Write = false;



        //第一步:调用socket()函数创建一个用于通信的套接字
        private Socket listenSocket;

        //字典集合:存储IP和Socket的集合
        private Dictionary<string, Socket> OnLineList = new Dictionary<string, Socket>();


        //编码格式
        Encoding econding = Encoding.Default;

        private void Button_OpenProtClick(object sender, EventArgs e)
        {
            if (isConnent)
            {
                MessageBox.Show("服务器已开启,请勿重复点击!");
                return;
            }


            if (!isOpenConnent)
            {
                //第一步:调用socket()函数创建一个用于通信的套接字
                listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


                isOpenConnent = true;
            }

            //第二步:给已经创建的套接字绑定一个端口号,这一般通过设置网络套接口地址和调用Bind()函数来实现
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(this.txb_ServerAdderess.Text.Trim()), int.Parse(this.txb_Prot.Text.Trim()));

            try
            {
                listenSocket.Bind(endPoint);
            }
            catch (Exception ex)
            {
                MessageBox.Show("服务器开启失败:" + ex.Message, "开启服务器");

                //listenSocket.Shutdown(SocketShutdown.Both);
                //listenSocket.Close();
                //MessageBox.Show("关闭服务器中......");
                isOpenConnent = false;
                return;
            }

            //第三步:调用listen()函数使套接字成为一个监听套接字
            listenSocket.Listen(10);

            //ShowMessage("服务器开启成功");
            MessageBox.Show("服务器开启成功");
            isConnent = true;
            this.Dispatcher.Invoke(new Action(() =>
            {
                txtb_serverData.Text = "服务器开启成功!等待客户端连接中......";
                btn_OpenConnent.Background = new SolidColorBrush(Colors.Green);
            }));

            if (isOpenConnent)
            {
                //开启一个线程监听
                Task.Run(new Action(() =>
            {
                ListenConnection();
            }
                ));
            }


        }

        private void ListenConnection()
        {
            try
            {
                while (true)
                {
                    Socket clientSocket = listenSocket.Accept();
                    string ip = clientSocket.RemoteEndPoint.ToString();

                    //MessageBox.Show(ip + "上线了");
                    this.Dispatcher.Invoke(new Action(() =>
                    {
                        txtb_ConnentDevice.Text = "当前连接设备:" + ip;
                    }));

                    Task.Run(() => ReceiveMsg(clientSocket));
                    Task.Run(() => WriteDeviceMsg(clientSocket));

                }
            }
            catch (Exception)
            {

                throw;
            }



        }

        /// <summary>
        /// 接收方法
        /// </summary>
        /// <param name="clientSocket"></param>
        private void ReceiveMsg(Socket clientSocket)
        {

            try
            {

                //    // 接收数据
                byte[] bytesToUse = new byte[60];
                int numberOfBytesRec = clientSocket.Receive(bytesToUse);
                string returndata = Encoding.ASCII.GetString(bytesToUse, 0, numberOfBytesRec);
                //Console.WriteLine("从客户端收到: " + returndata);
                this.Dispatcher.Invoke(new Action(() =>
                {
                    txtb_serverData.Text = "从客户端收到: " + returndata;
                }));

                while (true)
                {
                    numberOfBytesRec = clientSocket.Receive(bytesToUse);
                    returndata = Encoding.ASCII.GetString(bytesToUse, 0, numberOfBytesRec);
                    Thread.Sleep(10);
                    this.Dispatcher.Invoke(new Action(() =>
                    {
                        txtb_reData.Text = returndata;
                        txtb_serverData.Text = "从客户端收到: " + returndata;
                    }));
                    //Console.WriteLine("从客户端收到: " + returndata);

                    Thread.Sleep(1000);

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("接收报错:" + ex.Message);

            }

        }

        private void WriteDeviceMsg(Socket clientSocket)
        {
            // 发送数据回客户端
            string response = "Hello from server";
            byte[] msg = Encoding.ASCII.GetBytes(response);

            try
            {
                while (true)
                {
                    this.Dispatcher.Invoke(new Action(() =>
                    {
                        response = txb_WriteSN.Text.ToString() + txb_WriteNume.Text.ToString();
                        msg = Encoding.ASCII.GetBytes(response);

                    }));


                    if (btn_Write)
                    {
                        clientSocket.Send(msg);
                        //Console.WriteLine("发送到客户端: " + response);
                        btn_Write = false;
                    }
                    Thread.Sleep(1000);
                }

            }
            catch (Exception)
            {

                throw;
            }





        }


        /// <summary>
        /// 消息发送
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_WriteDevice_Click(object sender, EventArgs e)
        {
            btn_Write = true;
            return;
        }






    }
}

注意:要把当前连接PLC的网卡设置成服务器IP

最后启动测试就可以了;


网站公告

今日签到

点亮在社区的每一天
去签到