You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
10 KiB

3 years ago
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Text.RegularExpressions;
3 years ago
namespace TRI_TCP_Client
{
/// <summary>
/// Net : 提供静态方法,对常用的网络操作进行封装
/// </summary>
public sealed class Net
{
private Net() { }
/// <summary>
/// 向远程主机发送数据
/// </summary>
/// <param name="socket">要发送数据且已经连接到远程主机的 Socket</param>
/// <param name="buffer">待发送的数据</param>
/// <param name="outTime">发送数据的超时时间,以秒为单位,可以精确到微秒</param>
/// <returns>0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常</returns>
/// <remarks >
/// 当 outTime 指定为-1时将一直等待直到有数据需要发送
/// </remarks>
public static int SendData(Socket socket, byte[] buffer, int outTime)
{
int flag = 0;
3 years ago
if (socket == null || socket.Connected == false)
{
throw new ArgumentException("参数socket 为null或者未连接到远程计算机");
}
if (buffer == null || buffer.Length == 0)
{
throw new ArgumentException("参数buffer 为null ,或者长度为 0");
}
try
{
int left = buffer.Length;
int sndLen = 0;
while (true)
{
if (socket.Poll(outTime * 100, SelectMode.SelectWrite) == true)
3 years ago
{ // 收集了足够多的传出数据后开始发送
sndLen = socket.Send(buffer, sndLen, left, SocketFlags.None);
left -= sndLen;
if (left == 0)
{ // 数据已经全部发送
flag = 0;
break;
}
else
{
if (sndLen > 0)
{ // 数据部分已经被发送
continue;
}
else
{ // 发送数据发生错误
flag = -2;
break;
}
}
}
else
{ // 超时退出
flag = -1;
break;
}
}
}
catch (SocketException)
{
flag = -3;
}
return flag;
}
/// <summary>
/// 向远程主机发送文件
/// </summary>
/// <param name="socket" >要发送数据且已经连接到远程主机的 socket</param>
/// <param name="filePath">待发送的文件</param>
/// <param name="maxBufferLength">文件发送时的缓冲区大小</param>
/// <param name="outTime">发送缓冲区中的数据的超时时间</param>
/// <returns>0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误</returns>
/// <remarks >
/// 当 outTime 指定为-1时将一直等待直到有数据需要发送
/// </remarks>
public static int SendFile(Socket socket, string filePath, int maxBufferLength, int outTime)
{
if (filePath == null || maxBufferLength <= 0)
{
throw new ArgumentException("待发送的文件名称为空或发送缓冲区的大小设置不正确.");
}
int flag = 0;
try
{
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
long fileLen = fs.Length; // 文件长度
long leftLen = fileLen; // 未读取部分
int readLen = 0; // 已读取部分
byte[] buffer = null;
if (fileLen <= maxBufferLength)
{ //文件可以一次读取(+1指代结束标识符)
buffer = new byte[fileLen + 1];
readLen = fs.Read(buffer, 0, (int)(fileLen + 1));
buffer[fileLen] = (byte)'`';
flag = SendData(socket, buffer, outTime);
}
else
{
//循环读取文件,并发送
while (leftLen != 0)
{
if (leftLen < maxBufferLength)
{
buffer = new byte[leftLen];
readLen = fs.Read(buffer, 0, Convert.ToInt32(leftLen));
}
else
{
buffer = new byte[maxBufferLength];
readLen = fs.Read(buffer, 0, maxBufferLength);
}
if ((flag = SendData(socket, buffer, outTime)) < 0)
{
break;
}
leftLen -= readLen;
}
//在结尾带上结束标识符: "`"
SendData(socket, System.Text.Encoding.Default.GetBytes("`"), outTime);
}
fs.Flush();
fs.Close();
}
catch (IOException)
{
//读取待发送文件发生错误
flag = -4;
}
return flag;
}
/// <summary>
/// 使用TCP发送文件
/// </summary>
/// <param name="socket"></param>
/// <param name="path"></param>
/// <param name="bufsize"></param>
/// <param name="outTime"></param>
public static string TCPSend(Socket socket, string path, int maxBufferLength, int outTime)
{
string res = "";
string eqpName = "";
3 years ago
int _flag;
List<string> eqpNames = new List<string>();
//TODO: 根据需求修改具体的设备名
eqpNames.Add("2DAOI");
eqpNames.Add("3DAOI");
eqpNames.Add("SPI");
foreach (string item in eqpNames)
{
if (System.Text.RegularExpressions.Regex.IsMatch(path, item))
{
eqpName = item; break;
}
}
3 years ago
string _filename = Path.GetFileName(path);
_flag = Net.SendData(socket, Encoding.Default.GetBytes("1000&" + eqpName + "&" + _filename), outTime);
Console.WriteLine(_flag + " 文件发送 " + DateTime.Now.ToString("yyyy:MM:dd HH:mm:ss:ff"));
try
{
if (Net.SendFile(socket, path, maxBufferLength, outTime) != 0)
{
if (Net.SendFile(socket, path, maxBufferLength, outTime) != 0)
{
res = "发送失败";
}
else
{
res = "重发成功";
}
}
else
{
res = "发送成功";
}
}
catch (Exception ex)
{
res = "[ERR]" + ex.Message.ToString();
3 years ago
}
return res;
}
/// <summary>
/// 接收数据
/// </summary>
/// <param name="socket"></param>
/// <param name="buffer">size=25</param>
/// <returns>数据 or null</returns>
public static string[] RecvData(Socket socket, byte[] buffer)
{
if (socket == null || socket.Connected == false)
{
throw new ArgumentException("参数socket 为null或者未连接到远程计算机");
}
if (buffer == null || buffer.Length == 0)
{
throw new ArgumentException("参数buffer 为null ,或者长度为 0");
}
if (socket.Receive(buffer, 0, buffer.Length, SocketFlags.None) > 0)
{
string recv = Encoding.Default.GetString(buffer);
string[] array = Regex.Split(recv, "(&)");
return array;
}
return null;
}
/// <summary>
/// 接收并在本地创建文件
/// </summary>
/// <param name="socket"></param>
/// <param name="buffer"></param>
/// <param name="path"></param>
/// <returns>返回文件接收时间和大小</returns>
public static string RecvFile(Socket socket, byte[] buffer, string path)
{
int size = 0;
long len = 0;
DateTime oTimeBegin = DateTime.Now;
//创建文件流,然后让文件流来根据路径创建一个文件
FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
//从终端不停的接受数据然后写入文件里面只到接受到的数据为0为止则中断连接
while ((size = socket.Receive(buffer, 0, buffer.Length, SocketFlags.None)) > 0)
{
string flag = Encoding.Default.GetString(buffer, size - 1, 1);
if (flag.Equals("`"))
{
fs.Write(buffer, 0, size - 1);
len += size;
break;
}
else
{
fs.Write(buffer, 0, size);
len += size;
}
}
DateTime oTimeEnd = DateTime.Now;
TimeSpan oTime = oTimeEnd.Subtract(oTimeBegin);
fs.Flush();
fs.Close();
len -= 1;//去除文件尾标记占据空间
string store = (len / 1024.0) > 1.0 ? (len / 1024.0) + "kb" : len + "字节";
return $"接收文件{path}用时: {oTime}, 文件大小:{store}";
}
3 years ago
}
}