|
|
|
|
using System;
|
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Net.Sockets;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
if (socket == null || socket.Connected == false)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");
|
|
|
|
|
}
|
|
|
|
|
if (buffer == null || buffer.Length == 0)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException("参数buffer 为null ,或者长度为 0");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int flag = 0;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
int left = buffer.Length;
|
|
|
|
|
int sndLen = 0;
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
if ((socket.Poll(outTime * 100, SelectMode.SelectWrite) == true))
|
|
|
|
|
{ // 收集了足够多的传出数据后开始发送
|
|
|
|
|
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 = null;
|
|
|
|
|
int _flag;
|
|
|
|
|
//先发送一个标记:"1000"标记为传文件
|
|
|
|
|
//D:\KSATProjects\2021-10-ASM\settings\SPI\Lanto_HTTP.INI
|
|
|
|
|
string eqpName = System.Text.RegularExpressions.Regex.IsMatch(path, "AOI") ? "AOI" : "SPI";
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|