zoukankan      html  css  js  c++  java
  • 一个读取以太网设备的数据的socket

    经常需要用socket读取设备的数据,包括现在很多串口转以太网的东西,需要发送数据事先定义好的字节数据,然后等待返回字节数据。发送和接收的数据往往是固定长度,并且短时间要收到回复的。于是就手动做这么一个简单的类。

    使用方法很简单,new 一个socketclient同时定义好ip和端口,直接send(数据,超时时间,返回的数据长度),然后返回RetData,这里表明了返回是否成功,接收到的长度和数据

    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;
    
    namespace Common
    {
        public class SocketClient
        {
            public SocketClient(string ip, int port)
            {
                Ip = ip;
                Port = port;
                //定义一个套字节监听  包含3个参数(IP4寻址协议,流式连接,TCP协议)
                socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                result = new RetData();
            }
            //创建 1个客户端套接字 和1个负责监听服务端请求的线程  
            Socket socketClient = null;
            Thread threadClient = null;
            public EventHandler EvenNewData;
            string Ip = "127.0.0.1";
            int Port = 8888;
            public bool Connected { get { return socketClient.Connected; } }
            byte[] DataBuf = new byte[1024 * 1024];
            //定义一个1M的内存缓冲区 用于临时性存储接收到的信息
            public byte[] Data { get { return DataBuf; } }
            //默认为0表示不检测接收数据长度,如果不为0表示数据接收超过这个长度才会触发接收完成事件
            int _rcvDataLength = 0;
            //最大长度1024*1024
            public int FixRcvLength { get { return _rcvDataLength; } set { if (value <= DataBuf.Length) _rcvDataLength = value; } }
            RetData result;
            public bool ConnectToServer()
            {
                //定义一个套字节监听  包含3个参数(IP4寻址协议,流式连接,TCP协议)
                //socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //需要获取文本框中的IP地址
                IPAddress ipaddress = IPAddress.Parse(Ip);
                //将获取的ip地址和端口号绑定到网络节点endpoint上
                IPEndPoint endpoint = new IPEndPoint(ipaddress, Port);
                //这里客户端套接字连接到网络节点(服务端)用的方法是Connect 而不是Bind
                if (!socketClient.Connected)
                {
                    try
                    {
                        socketClient.Connect(endpoint);
                        //创建一个线程 用于监听服务端发来的消息
                        threadClient = new Thread(RecMsg);
                        //将窗体线程设置为与后台同步
                        threadClient.IsBackground = true;
                        //启动线程
                        threadClient.Start();
                    }
                    catch (Exception ex)
                    {
                        Log.WriteLogs(ex.Message.ToString());
                        return false;
                    }
                }
                return socketClient.Connected;
            }
            public void DisconnectFromServer()
            {
                if (socketClient.Connected) socketClient.Disconnect(true);
            }
            /// <summary>
            /// 接收服务端发来信息的方法
            /// </summary>
            private void RecMsg()
            {
                while (true) //持续监听服务端发来的消息
                {
                    //将客户端套接字接收到的数据存入内存缓冲区, 并获取其长度
                    int length = socketClient.Receive(DataBuf);
                    //将数据拷贝,并根据已经接收到的数据数量累加到数据缓存区,
                    Buffer.BlockCopy(DataBuf, 0, DataBuf, result.revLength, length);
                    //累加已经接收到的数据长度
                    result.revLength += length;
                    if (result.revLength >= FixRcvLength)
                    {//如果累加的数据长度超过指定的长度
                        if (FixRcvLength == 0 || result.revLength == FixRcvLength)
                        {//如果没有指定数据长度,或者累加的数据长度==指定的长度则触发事件,并发送数据,否则丢弃数据
                            byte[] arrData = new byte[result.revLength];
                            Array.Copy(DataBuf, arrData, result.revLength);
                            result.Data = arrData;
                            result.Code = 0;
                            result.Message = "successful";
                            result.IsSuccessful = true;
                        }
                        result.revLength = 0;
                    }
                }
            }
            /// <summary>
            /// 发送数据并等待返回数据
            /// </summary>
            /// <param name="sendMsg">发送的字符串数据</param>
            /// <param name="monitorTime">等待的超时毫秒,如果超过时间还没收到返回指定的数据长度,则返回读取错误</param>
            /// <param name="returnBytes">等待返回的数据长度,0表示不管多长都返回</param>
            /// <returns></returns>
            public RetData Send(string sendMsg, int monitorTime, int returnBytes = 0)
            {
                byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
                return Send(sendMsg, monitorTime, returnBytes);
            }
            /// <summary>
            /// 发送数据并等待返回数据
            /// </summary>
            /// <param name="sendMsg">发送的数据</param>
            /// <param name="monitorTime">等待的超时毫秒,如果超过时间还没收到返回指定的数据长度,则返回读取错误</param>
            /// <param name="returnBytes">等待返回的数据长度,0表示不管多长都返回</param>
            /// <returns></returns>
            public RetData Send(byte[] sendMsg, int monitorTime, int returnBytes = 0)
            {
                result = new RetData();
                MonitorTime = monitorTime;
                FixRcvLength = returnBytes;
                if (socketClient != null)
                {
                    if (!Connected)
                    {
                        ConnectToServer();
                        Thread.Sleep(500);
                    }
                    if (Connected)
                    {
                        //调用客户端套接字发送字节数组
                        socketClient.Send(sendMsg);
                        //将发送的信息追加到聊天内容文本框中
                    }
                    else
                    {
                        result.Message = "connect to server failure";
                    }
                    Monitor(MonitorTime);
                }
                else
                {
                    result.Message = "socketClient is null";
                }
                return result;
            }
            /// <summary>
            /// 发送数据并等待返回数据
            /// </summary>
            /// <param name="sendMsg">发送的数据</param>
            /// <param name="monitorTime">等待的超时毫秒,如果超过时间还没收到返回指定的数据长度,则返回读取错误</param>
            /// <param name="returnBytes">等待返回的数据长度,0表示不管多长都返回</param>
            /// <returns></returns>
            public Task<RetData> SendAsync(byte[] sendMsg, int monitorTime, int returnBytes = 0)
            {
                return Task.Run(() =>
                {
                    return Send(sendMsg, monitorTime, returnBytes) ;
                });
            }
            int MonitorTime = 0;
            private void Monitor(int monitortime)
            {
                int _time = monitortime;
                while (!result.IsSuccessful && _time > 0)
                {
                    Thread.Sleep(10);
                    _time -= 10;
                }
                result.Message = "time out";
            }
            ~SocketClient()
            {
                socketClient.Disconnect(false);
                socketClient.Dispose();
            }
        }
        [Serializable]
        public class RetData
        {
            public bool IsSuccessful { get; set; } = false;
            public byte[] Data { get; set; }
            public string Message { get; set; }
            public int Code { get; set; } = 0;
            public int revLength { get; set; } = 0;
        }
    }
    

      

  • 相关阅读:
    Objective--C三大特性:封装,继承,多态(零碎笔记)
    零碎的知识点
    Objective--C之《文件操作》练习代码
    Objective--C的Foundation frame之NSMutableDictionary代码
    Objective--C的Foundation frame之NSMutableArray代码
    Objective--C随笔2016年8月7日
    关于OC中的委托delegate
    javascript 绝对路径工具类
    IE 弹出框处理经验
    InputStream和OutputStream 何时使用
  • 原文地址:https://www.cnblogs.com/franklin2018/p/11867315.html
Copyright © 2011-2022 走看看