一个读取以太网设备的数据的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;
    }
}

  

posted @ 2019-11-15 16:00  冬日厦语  阅读(1336)  评论(0编辑  收藏  举报