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

浙公网安备 33010602011771号