plc通讯的握手信号_工控:C#中的串口,网口和PLC通讯

本文介绍了C#在工控中的串口和网口通讯方式,包括RS232和RS485串口协议以及TCP/IP的TCP和UDP协议。详细阐述了与PLC进行通信时的握手过程,以欧姆龙FINS协议为例,展示了如何建立连接、发送命令以及读写数据。同时提到了在C#中使用SerialPort类进行串口通信以及TCP客户端和服务器的实现。
摘要由CSDN通过智能技术生成

一.串口通讯方式

首先,串口、UART口、COM口、USB口是指的物理接口形式(硬件)。而TTL、RS-232、RS-485是指的电平标准(电信号)。

串口:串口是一个泛称,UART、TTL、RS232、RS485都遵循类似的通信时序协议,因此都被通称为串口

工控中常用的协议:RS232 RS485

RS232:是电子工业协会(Electronic Industries Association,EIA) 制定的异步传输标准接口,同时对应着电平标准和通信协议(时序),其电平标准:+3V~+15V对应0,-3V~-15V对应1。rs232 的逻辑电平和TTL 不一样但是协议一样

RS485:RS485是一种串口接口标准,为了长距离传输采用差分方式传输,传输的是差分信号,抗干扰能力比RS232强很多。两线压差为-(2~6)V表示0,两线压差为+(2~6)V表示1

常见的D型9针串口(通俗说法)。在台式电脑后边都可以看到。这种接口的协议只有两种:RS-232和RS-485

二.网口通讯方式

TCP/IP 是互联网相关的各类协议族的总称,比如:TCP,UDP,IP,FTP,HTTP,ICMP,SMTP 等都属于 TCP/IP 族内的协议。像这样把与互联网相关联的协议集合起来总称为 TCP/IP。也有说法认为,TCP/IP 是指 TCP 和 IP 这两种协议。还有一种说法认为,TCP/IP 是在 IP 协议的通信过程中,使用到的协议族的统称。

工控中常用的通讯有TCP和UDP

这两个区别就是:TCP 用于在传输层有必要实现可靠传输的情况。由于它是面向有链接并具备顺序控制、重发控制等机制的,所以他可以为应用提供可靠的传输。 而在一方面,UDP 主要用于那些对高速传输和实时性有较高要求的通信或广播通信。 我们举一个通过 IP 电话进行通话的例子。如果使用 TCP,数据在传送途中如果丢失会被重发,但这样无法流畅的传输通话人的声音,会导致无法进行正常交流。而采用 UDP,他不会进行重发处理。从而也就不会有声音大幅度延迟到达的问题。即使有部分数据丢失,也支持会影响某一小部分的通话。此外,在多播与广播通信中也是用 UDP 而不是 TCP。

三.确定PLC硬件

首先要确定PLC是否支持网口或者串口通信,大多数都支持RS232,TCP或者UDP,有的可能要购买拓展模块才能进行通信

四.确定PLC通信协议

通信协议:是指双方实体完成通信或服务所必须遵循的规则和约定。通过通信信道和设备互连起来的多个不同地理位置的数据通信系统,要使其能协同工作实现信息交换和资源共享,它们之间必须具有共同的语言。交流什么、怎样交流及何时交流,都必须遵循某种互相都能接受的规则。这个规则就是通信协议。

以下以欧姆龙FINS通信协议为例

一,握手命令
1、客户端向服务器发送命令
00000000。这个命令长20字节,分成5组4字节。分别是:头(FINS) + 长度(Hex0C) + 命令(00000000)+ 错误码(00000000) + 客户机节点地址。
46494E53是FINS的ASCII码值,即命令头。
0000000C是命令长度20。
00000000是命令码。
00000000是错误码。
00000005是客户节点地址,即电脑IP地址的末位。
在发送区输入:46494E53 0000000C 00000000 00000000 00000005
点击发送,PLC立即回应:46494E53 00000010 00000001 00000000 00000005 00000020
到此我们已经成功地完成了第一步!接下来需要的就是之前介绍过的HostLink协议里面FINS的知识了。

c167817273c66c04f454d7ca53471fb6.png

图3 网络调试助手 握手成功2、这个是服务器端(PLC)向客户端(电脑)发送的命令00000001。这个命令长24字节,分成6组4字节。分别是:头(FINS)+ 长度(Hex10) + 命令(00000001) + 错误码 + 客户机节点地址 + 服务器地址。
上面的命令错误代码为0,客户端ip地址05已被服务器32(hex20)成功记录。
如果发生错误,服务器回应的命令会包含错误码,连接断开,端口立刻关闭。当连接建立之后,不要再次发送这个命令,否则服务器会返回03错误码,即不支持的命令。全部的错误代码如下:
十六进制错误码 含义
00000000 正常
00000001 头不是‘FINS’ (ASCII code)。
00000002 数据太长。
00000003 不支持的命令。
00000020 所有的连接被占用。
00000021 制定的节点已经连接。
00000022 未被指定的IP地址试图访问一个被保护的节点。
00000023 客户端FINS节点地址超范围。
00000024 相同的FINS节点地址已经被使用。
00000025 所有可用的节点地址都已使用。二、FINS帧发送命令
如果向服务器发送FINS帧,就要用到这个命令。由于FINS帧长度是12-2012,因此命令长度可变,头(FINS)+长度+命令(00000002)+错误码+FINS帧。FINS命令帧内容可参考欧姆龙OMRON PLC之HostLink通讯协议-FINS命令W字/位操作篇,里面有存储区代码和操作代码的内容。例2-1、读DM0开始的2个通道:发送:46494E53 0000001A 00000002 00000000 80000200 20000005 00FF0101 82000000 000220000005:20是目标地址,05是源地址;
00FF0101 :0101是读操作;
82000000:82是DM存储区代码,000000是起始地址;
0002:是数量。
返回:46494E53 0000001A 00000002 00000000 C0000200 05000020 00FF0101 00001234 567800001234:0000代表操作成功,1234是读回的第一个字,即D0=Hex1234,
5678:D1=Hex5678例2-2、W210寄存器写入Hex0388:
发送:46494E53 0000001C 00000002 00000000 80000200 20000005 00FF0102 B100D200 00010388
20000005:20是目标地址,05是源地址;
00FF0102:0102是写操作代码;
B100D200:B1是W字代码,00D2是起始地址,Hex00D2=212,;
00010388:是写入数量,0388是写入首个内容;
回应:46494E53 00000016 00000002 00000000 C0000200 05000020 00FF0102 0000
0102后面紧跟的0000代表写入成功。例2-3、W210寄存器读取:发送:46494E53 0000001A 00000002 00000000 80000200 20000005 00FF0101 B100D200 0001
20000005:20是目标地址,05是源地址;
00FF0101:0101是读操作代码;
B100D200:B1是W字代码,00D2是起始地址,Hex00D2=212,;
0001:是读取数量。
回应:46494E53 00000018 00000002 00000000 C0000200 05000020 00FF0101 00000388
0102后面紧跟的0000代表读取成功,W210=Hex0388例2-4、强制W212.01=On:
发送: 46494E53 0000001C 00000002 00000000 80000200 20000005 00FF2301 00010001 3100D401
20000005:20是目标地址,05是源地址;
00FF2301:2301是强制操作代码;
00010001:前面的0001是数量,后面的0001代表强制置位操作;
3100D401:31是W位代码,00D401是起始地址,Hex00D4.01=212.01。
回应:46494E53 00000016 00000002 00000000 C0000200 05000020 00FF2301 0000
2301后面紧跟的0000表示操作成功。
注意在CX-Programmer查看窗口中W212.01的值1后面的(强制)字样。

15198fc5006a2d8fead832a341212aa1.png

图4 网络调试助手 强制置位

6e3fea2a1d88f8e7039904a4e6f55805.png

图5 CX-Programmer 强制置位成功例2-5、强制W212.01=Off:
发送:46494E53 0000001C 00000002 00000000 80000200 20000005 00FF2301 00010000 3100D401
20000005:20是目标地址,05是源地址;
00FF2301:2301是强制操作代码;
00010000:0001是数量,0000代表强制复位操作;
3100D401:31是W位代码,00D401是起始地址,Hex00D4.01=212.01。
回应:46494E53 00000016 00000002 00000000 C0000200 05000020 00FF2301 0000
2301后面紧跟的0000表示操作成功。例2-6、取消W212.01强制:
发送:46494E53 0000001C 00000002 00000000 80000200 20000005 00FF2301 0001FFFF 3100D401
20000005:20是目标地址,05是源地址;
00FF2301:2301是强制操作代码;
0001FFFF:0001是数量,FFFF代表取消强制操作;
3100D401:31是W位代码,00D401是起始地址,Hex00D4.01=212.01。
回应:46494E53 00000016 00000002 00000000 C0000200 05000020 00FF2301 0000
2301后面紧跟的0000表示操作成功。
注意在CX-Programmer查看窗口中W212.01的值0后面的(强制)字样不见了,表示已经成功地取消了强制。

e0d4c289e2f56195466973e777bde64e.png

图6 网络调试助手 取消强制

746d89111a4fcbe59aa5359c5cdb6c21.png


图7 CX-Programmer 取消强制成功

与CIO不同,对于W、A、H及D 这样的寄存器进行位操作,其实不用强制操作,直接写入更简洁,可以减少操作步骤,下面以W位操作为例介绍。

例2-7、W212.01 按位置位:

发送: 46494E53 0000001B 00000002 00000000 80000200 20000005 00FF0102 3100D401 000101
20000005:20是目标地址,05是源地址;
00FF0102:0102是寄存器写操作代码;
3100D401:31是W位代码,00D401是地址,Hex00D4.01=212.01;

000101:0001是数量,01代表写入值1;
回应:

46494E53 00000016 00000002 00000000 C0000200 20000005 00FF0102 0000

0102后面紧跟的0000表示操作成功。

例2-8、W212.01 按位复位:
发送: 46494E53 0000001B 00000002 00000000 80000200 20000005 00FF0102 3100D401 000100

20000005:20是目标地址,05是源地址;
00FF0102:0102是寄存器写操作代码;
3100D401:31是W位代码,00D401是地址,Hex00D4.01=212.01;

000100:0001是数量,00代表写入值0;

回应:

46494E53 00000016 00000002 00000000 C0000200 20000005 00 FF0102 0000

0102后面紧跟的0000表示操作成功。

五.使用C#进行通信

1.串口

串口在C#中使用的是SerialPort这个类

要注意通讯协议中报文内容是16进制,还是ASCII码,还是就是普通的字符串,有格式的话注意发送和接收的报文需要转换

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.IO.Ports;using System.Threading;using System.Windows.Forms;public class SerialOP : IDisposable    {        private SerialPort Comport = new SerialPort();        private AutoResetEvent _manualEvent = new AutoResetEvent(false);        private object _lockRead = new object();        private object _lockWrite = new object();        private byte[] _reivedData;        private string reive=null;        private object onRecive =new object();        public delegate void UpdateByteDelegate(byte[] reive);        public event UpdateByteDelegate UpdateByte;        ///         /// 打开串口        ///         ///         ///         ///         ///         ///         public bool Open(string com, string bps, string databit, string stopbit, string check)        {            try            {                if (Comport.IsOpen)                    Comport.Close();                Thread.Sleep(100);                //串口端口号                Comport.PortName = com;                //串口波特率                Comport.BaudRate = int.Parse(bps);                //串口数据位                Comport.DataBits = int.Parse(databit);                //串口停止位                switch (stopbit)                {                    case "0":                        Comport.StopBits = StopBits.None;                        break;                    case "1":                        Comport.StopBits = StopBits.One;                        break;                    case "1.5":                        Comport.StopBits = StopBits.OnePointFive;                        break;                    case "2":                        Comport.StopBits = StopBits.Two;                        break;                    default:                        Comport.StopBits = StopBits.None;                        break;                }                //串口奇偶校验                switch (check)                {                    case "无":                        Comport.Parity = Parity.None;                        break;                    case "奇校验":                        Comport.Parity = Parity.Odd;                        break;                    case "偶校验":                        Comport.Parity = Parity.Even;                        break;                    default:                        Comport.Parity = Parity.None;                        break;                }                //Comport.ReceivedBytesThreshold = 1;//1字节触发数据获取                //Comport.DataReceived += new SerialDataReceivedEventHandler(OnReceived);                                       Comport.Open();                Comport.DtrEnable = true;                Comport.RtsEnable = true;                return true;            }            catch (Exception ex)            {                LogHelper.error(ex.ToString());                MessageBox.Show("连续打开关闭串口出现错误:" + ex.Message,"SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);                return false;            }        }        ///         /// 检测串口是否打开        ///         ///         private bool IsOpen()        {            try            {                if (Comport == null)                    return false;                if (Comport.IsOpen)                    return true;                else                    return false;            }            catch (Exception ex)            {                LogHelper.error(ex.ToString());                MessageBox.Show("检测串口是否打开出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);                return false;            }        }        private void OnReceived(object sender, SerialDataReceivedEventArgs e)        {                     try            {                lock (onRecive)                {                    byte[] reive = new byte[Comport.BytesToRead];                    Comport.Read(reive, 0, Comport.BytesToRead);                    UpdateByte.Invoke(reive);                }                      }                catch (Exception ex)            {                LogHelper.error(ex.ToString());                MessageBox.Show("串口接收数据出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);                          }            finally            {                _manualEvent.Set();                          }        }        ///         /// 字符串转ASII码发送        ///         ///         public void Send_ASCII(string str)        {            try            {                lock (_lockWrite)                {                    var ByteSendW = Encoding.ASCII.GetBytes(str );//把发送数据转换为ASCII数组                    Comport.Write(ByteSendW, 0, ByteSendW.Length);                }            }            catch (Exception ex)            {                LogHelper.error(ex.ToString());                MessageBox.Show("串口发送数据出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);            }        }        ///         /// 发送16进制数组,需要用,隔开        ///         ///         ///         public void Send_HEX(string Hex)        {            try            {                lock (_lockWrite)                {                    //16进制字符串转换成16进制数组                    var HEX = Hex.Split(',').Select(temp => "0x" + temp).Select(temp => (byte)Convert.ToInt32(temp, 16)).ToArray();                    Comport.Write(HEX, 0, HEX.Length);                }            }            catch (Exception ex)            {                LogHelper.error(ex.ToString());                MessageBox.Show("串口发送数据出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);            }        }        ///         /// 发送字符串不转换        ///         ///         public void Send_String(string str)        {            try            {                lock (_lockWrite)                {                    Comport.Write(str);                }            }            catch (Exception ex)            {                LogHelper.error(ex.ToString());                MessageBox.Show("串口发送数据出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);            }        }        ///         /// 接收ASCII码,并转换成字符串        ///         ///         public void Read_ASCII(out string str)        {            str = "error";            try            {                lock (_lockRead)                {                    if (Comport.BytesToRead == 0)                    {                        LogHelper.error("缓存区没有数据");                        return;                    }                    for (int i = 0; i < 100; i++)//读取100个字节                    {                        if (Comport.BytesToRead == 0)                        {                            str = reive;                            reive = null;                            break;                        }                        string reivestring = "";                        _reivedData = new byte[1];                        Comport.Read(_reivedData, 0, _reivedData.Length);                        reivestring = Encoding.ASCII.GetString(_reivedData);                                             reive += reivestring;                        //Comport.DiscardInBuffer();                                   }                }            }            catch (Exception ex)            {                str = ex.ToString();                LogHelper.error(ex.ToString());                MessageBox.Show("串口读取数据出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);            }        }        ///         /// 接收字符串,不进行任何转换        ///         ///         public void Read_String(out string str)        {            str = "error";            try            {                lock (_lockRead)                {                    if (Comport.BytesToRead == 0)                    {                        LogHelper.error("缓存区没有数据");                        return;                    }                    for (int i = 0; i < 100; i++)//读取100个字节                    {                        if (Comport.BytesToRead == 0)                        {                            str = reive;                            reive = null;                            break;                        }                        _reivedData = new byte[1];                        Comport.Read(_reivedData, 0, _reivedData.Length);                                       reive += _reivedData[0].ToString() + " ";                    }                }            }            catch (Exception ex)            {                str = ex.ToString();                LogHelper.error(ex.ToString());                MessageBox.Show("串口读取数据出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);            }        }        ///         /// 接收到16进制,转成字符串        ///         ///         public void Read_HEX_String(out string str)        {            str = "error";            try            {                lock (_lockRead)                {                    if (Comport.BytesToRead == 0)                    {                        LogHelper.error("缓存区没有数据");                        return;                    }                    for (int i = 0; i < 100; i++)//读取100个字节                    {                        if (Comport.BytesToRead == 0)                        {                            reive = reive.Substring(0, reive.Length - 1);//移除最后一位逗号                            str = reive;                            reive = null;                            break;                        }                        _reivedData = new byte[1];                        Comport.Read(_reivedData, 0, _reivedData.Length);                        reive += _reivedData[0].ToString("x2").ToUpper() + ",";                    }                }            }            catch (Exception ex)            {                str = ex.ToString();                LogHelper.error(ex.ToString());                MessageBox.Show("串口读取数据出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);            }        }        ///         /// 关闭串口        ///         public void Close()        {            try            {                if (Comport.IsOpen)                    Comport.Close();            }            catch (Exception ex)            {                LogHelper.error(ex.ToString());                MessageBox.Show("关闭串口出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);            }        }        ///         /// 释放串口        ///         public void Dispose()        {            try            {                if (Comport.IsOpen)                    Comport.Close();                Comport.Dispose();            }            catch (Exception ex)            {                         LogHelper.error(ex.ToString());                MessageBox.Show("释放串口出现错误:" + ex.Message, "SerialPort---Message", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);            }            //Comport.DataReceived -= new SerialDataReceivedEventHandler(Comport_DataReceived);        }        ///         /// CRC16校验        ///         ///         ///         public string CRCCalc(string data)        {            string[] datas = data.Split(' ');            List bytedata = new List();            foreach (string str in datas)            {                bytedata.Add(byte.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier));            }            byte[] crcbuf = bytedata.ToArray();            //计算并填写CRC校验码            int crc = 0xffff;            int len = crcbuf.Length;            for (int n = 0; n < len; n++)            {                byte i;                crc = crc ^ crcbuf[n];                for (i = 0; i < 8; i++)                {                    int TT;                    TT = crc & 1;                    crc = crc >> 1;                    crc = crc & 0x7fff;                    if (TT == 1)                    {                        crc = crc ^ 0xa001;                    }                    crc = crc & 0xffff;                }            }            string[] redata = new string[2];            redata[1] = Convert.ToString((byte)((crc >> 8) & 0xff), 16);            redata[0] = Convert.ToString((byte)((crc & 0xff)), 16);            return redata[0].ToUpper() + " " + redata[1].ToUpper();        }    }

2.网口

网口分客户端和服务器,协议有TCP和UDP

以下以TCP为例

TCP客户端

   public class TcpClient    {       public bool connected =false ;        Socket  socketClient;//客户端接口        Task  threadAcceptClient,//客户端接收线程              threadClient; //客户端线程        private string IpAddress = string.Empty;        private int Port = 0;        public TcpClient(string IpAddress, int Port)        {            this.IpAddress = IpAddress;            this.Port = Port;            ClientConnectSever();        }      ///       /// 客户端连接服务器      ///         public bool ClientConnectSever()        {            IPAddress ip = IPAddress.Parse(IpAddress);            IPEndPoint port = new IPEndPoint(ip, Port);//服务器port            //创建TCP类型端口            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            try            {                socketClient.Connect(port);                connected = true;                return true;            }            catch (Exception ex)            {                LogHelper.error(IpAddress+"连接服务器失败:" + ex.Message);                return false;            }        }        public void ColseConnect()        {            socketClient.Close();                }        public bool ClientSendData(string data)        {                       if (!connected)            {                LogHelper.error(IpAddress+"未连接到服务器");                return false;            }            byte[] msg = Encoding.Default.GetBytes(data);            try            {                NetworkStream netStream = new NetworkStream(socketClient);                           netStream.Write(msg, 0, msg.Length);                netStream.Flush();                return true;            }            catch (Exception ex)            {                LogHelper.error(IpAddress+"发送失败:" + ex.Message);                return false;            }        }        public string ClientReadData()        {            try            {                if (!connected)                {                    LogHelper.error(IpAddress+"未连接到服务器");                    return "error";                }                NetworkStream netStream = new NetworkStream(socketClient);                byte[] dataSize = new byte[1024];                netStream.Read(dataSize, 0, dataSize.Length);                var Result = Encoding.Default.GetString(dataSize).TrimEnd('0');                if (Result.Length > 1)                    return Result;                else                    return string.Empty;                //this.rtb_accept1.Rtf = Encoding.Unicode.GetString(message);            }            catch (Exception ex)            {                LogHelper.error(IpAddress+"读取数据失败:" + ex.Message);                return "error";            }        }           }

TCP服务器

  public class TcpServer    {              public delegate void UpdateObjectDelegate(object sender);        public event UpdateObjectDelegate UpdataDataString;        public event UpdateObjectDelegate UpdateMessage;        private string IpAddress = string.Empty;        private int Port = 0;        public TcpServer(string IpAddress, int Port)        {            this.IpAddress = IpAddress;            this.Port = Port;        }        static Socket serverSocket;        List ClientList = new List(); //客户端列表        public bool connected = false;        public void StartListen()        {                             Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                         serverSocket = socket;                //ip port                  socket.Bind(new IPEndPoint( IPAddress.Parse(IpAddress), Port));                //listen                  socket.Listen(10);//连接等待队列                             ThreadPool.QueueUserWorkItem(new WaitCallback(this.AcceptClientConnect), socket);                                }        private void AcceptClientConnect(object socket)        {            var serverSocket = socket as Socket;            UpdateMessage.Invoke("服务器开始监听");                    while (true)            {                try                {                    var proxSocket = serverSocket.Accept();                    ClientList.Add(proxSocket);                    UpdateMessage.Invoke((object)("客户端" + proxSocket.RemoteEndPoint.ToString() + "连接上了"));                    //接受消息                      ThreadPool.QueueUserWorkItem(new WaitCallback(this.ReceiveData), proxSocket);                    connected = true;                }                catch (Exception e)                {                    UpdateMessage.Invoke("服务器监听错误:" + e.ToString());                    connected = false;                }            }        }        private void ReceiveData(object obj)        {            Socket proxSocket = obj as Socket;            byte[] data = new byte[1024 * 1024];            while (true)            {                int readLen = 0;                try                {                    readLen = proxSocket.Receive(data, data.Length,0);                                    //if (readLen <= 0)                    //{                    //    //客户端正常退出                      //    UpdateMessage.Invoke(string.Format("客户端{0}正常退出", proxSocket.RemoteEndPoint.ToString()));                    //    ClientList.Remove(proxSocket);                    //    CloseListen(proxSocket);                    //    connected = false;                    //    return;//方法结束->终结当前接受客户端数据的异步线程                      //}                    string txt = Encoding.Default.GetString(data, 0, readLen).TrimEnd('0');                    if(txt.Length>1)                    UpdataDataString.Invoke(txt);                }                catch (Exception ex)                {                    //异常退出时                      UpdateMessage.Invoke(string.Format("客户端{0}非正常退出,原因{1}", proxSocket.RemoteEndPoint.ToString(), ex.ToString()));                    ClientList.Remove(proxSocket);                    CloseListen(proxSocket);                    connected = false;                    return;                }                                   }        }        private void CloseListen(Socket proxSocket)        {            try            {                if (proxSocket.Connected)                {                    proxSocket.Shutdown(SocketShutdown.Both);                    proxSocket.Close(100);                    connected = false;                }            }            catch (Exception)            {                UpdateMessage("服务器关闭发生异常");                connected = false;            }        }        public bool ServerSendData(string msg)        {            try            {                foreach (Socket s in this.ClientList)                {   //服务端广播式发送给客户端                    (s as Socket).Send(Encoding.Default.GetBytes(msg));                }                return true;            }            catch            {                return false;            }        }    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值