110,566
社区成员
发帖
与我相关
我的任务
分享
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace CheckUpAccount
{
/// <summary>
/// 功 能:
/// 数据报文收发器
/// 描 述:
/// 只对数据报文提供接收,发送功能
///
///
/// </summary>
public class PacketTransmitter
{
private NetworkStream ns;
private int sleepMilliseconds;
private int timeOutSeconds;
private int sleepCount;
private TcpClient client;
private Encoding encoding;
public PacketTransmitter(TcpClient client, Encoding encoding, int sleepMilliseconds, int timeOutSeconds)
{
this.encoding = encoding;
this.ns = client.GetStream();
this.client = client;
this.sleepMilliseconds = sleepMilliseconds;
this.timeOutSeconds = timeOutSeconds;
this.sleepCount = timeOutSeconds * 1000 / sleepMilliseconds;
}
#region 数据的接收方法Receive
/// <summary>
/// 异步接收一个完整数据包 包格式为头部指定字节指示报文全长。一般为4
/// </summary>
/// <param name="headLength">包头的长度</param>
/// <returns></returns>
public byte[] ReceiveOnePacket(int headLength)
{
byte[] headByte = new byte[headLength]; //包头
byte[] bodyByte = null; //包体
byte[] packetByte = null; //全包
try
{
ReceiveByte(headByte); //1、接收包头
bodyByte = new byte[int.Parse(encoding.GetString(headByte)) - headLength];
ReceiveByte(bodyByte); //2、接收包体
if (headByte == null || bodyByte == null)
{
return null;
}
packetByte = new byte[headByte.Length + bodyByte.Length]; //3、还原全包
headByte.CopyTo(packetByte, 0);
bodyByte.CopyTo(packetByte, headByte.Length);
}
catch (Exception)
{
return null;
}
return packetByte;
}
/// <summary>
/// 根据指定长度,从网络流中接收相应的数据。
/// </summary>
/// <param name="ns">要读取的网络流</param>
/// <param name="length">要读取的字节长度</param>
/// <returns></returns>
public byte[] ReceiveLength(int length)
{
byte[] recByte = new byte[length];
ReceiveByte(recByte);
return recByte;
}
/// <summary>
/// 这是收数据的基方式,不对外公开。根据接收字节数组的元素长度从网络流中读取相应长度的数据到数组中。如果发生错误接收数组为NULL
/// </summary>
/// <param name="ns">要读取的网络流</param>
/// <param name="receiveByte">待接收的字节数组</param>
private void ReceiveByte(byte[] receiveByte)
{
IAsyncResult iar = ns.BeginRead(receiveByte, 0, receiveByte.Length, null, null);
int count = sleepCount;
while (!iar.IsCompleted)
{
//if (count <= 0)
//{
// receiveByte = null;
// return;
//}
Thread.Sleep(sleepMilliseconds);
//count--;
}
try
{
ns.EndRead(iar);
return;
}
catch (Exception)
{
receiveByte = null;
return;
}
}
//public byte[] ReceiveByteFragment(int bufferSize)
//{
// return null;
//}
#endregion
#region 数据的发送方法Send
/// <summary>
/// 发送数据
/// </summary>
/// <param name="sendByte">要发送的数据字节数组</param>
/// <returns></returns>
public bool Send(byte[] sendByte)
{
IAsyncResult iar = ns.BeginWrite(sendByte, 0, sendByte.Length, null, null);
int count = sleepCount;
while (!iar.IsCompleted)
{
//if (count <= 0)
//{
// return false;
//}
Thread.Sleep(sleepMilliseconds);
//count--;
}
try
{
ns.Flush();
ns.EndWrite(iar);
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="sendByte">要发送的数据字节数组</param>
/// <param name="offset">数据字节数组中开始发送的位置</param>
/// <param name="size">要发送的字节数</param>
/// <returns></returns>
public bool Send(byte[] sendByte,int offset,int size )
{
IAsyncResult iar = ns.BeginWrite(sendByte, offset,size, null, null);
int count = sleepCount;
while (!iar.IsCompleted)
{
//if (count <= 0)
//{
// return false;
//}
Thread.Sleep(sleepMilliseconds);
//count--;
}
try
{
ns.Flush();
ns.EndWrite(iar);
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 分片发送数据流
/// </summary>
/// <param name="stream">要发送的流</param>
/// <param name="bufferSize">缓存大小</param>
/// <returns></returns>
public bool SendFragment(Stream stream, int bufferSize)
{
BinaryReader br = new BinaryReader(stream, encoding);
int count = sleepCount; //循环次数
int readCount = 0; //当前读到的文件流字节数
int currentPosit = 0; //当前文件流的位置
byte[] sendBufs = new byte[bufferSize]; //发送缓存
while ((readCount = br.Read(sendBufs, currentPosit, sendBufs.Length)) != 0)
{
if (!Send(sendBufs))
{
return false;
}
currentPosit += readCount;//手动提升当前流位置
}
return true;
}
#endregion
/// <summary>
/// 关闭收发器。尝试在SOCKET上关闭收发,关闭SOCKET连接,关闭TcpClient对象
/// </summary>
public void Close()
{
try
{
client.Client.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
}
try
{
client.Client.Close();
}
catch (Exception)
{
}
try
{
client.Close();
}
catch (Exception)
{
}
}
}
}
private void ReceiveByte(byte[] receiveByte)
{
IAsyncResult iar = ns.BeginRead(receiveByte, 0, receiveByte.Length, null, null);
int count = sleepCount;
if (!iar.IsCompleted)
{
if (count <= 0)
{
receiveByte = null;
return;
}
Thread.Sleep(sleepMilliseconds);
count--;
}
try
{
ns.EndRead(iar);
return;
}
catch (Exception)
{
receiveByte = null;
return;
}
public bool Send(byte[] sendByte,int offset,int size )
{
IAsyncResult iar = ns.BeginWrite(sendByte, offset,size, null, null);
int count = sleepCount;
if (!iar.IsCompleted)
{
if (count <= 0)
{
return false;
}
Thread.Sleep(sleepMilliseconds);
count--;
}
try
{
ns.EndWrite(iar);
ns.Flush();
return true;
}
catch (Exception)
{
return false;
}
}
public bool SendFile(string path, int bufferSize)
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
int count = sleepCount; //循环次数
int readCount = 0; //当前读到的文件流字节数
byte[] sendBufs = new byte[bufferSize]; //发送缓存
int fileLength = (int)fs.Length;
string fileName = Path.GetFileName(path);
byte[] packetFirst = Joinhead4(string.Format("|{0}|{1}|", fileName, fileLength.ToString()));
if (!pt.Send(packetFirst)) //发送头包
return false;
#region 关键代码
while ((readCount = fs.Read(sendBufs,0,sendBufs.Length)) != 0)
{//以缓存大小分片循环发送文件内容
if (!pt.Send(sendBufs,0,readCount))
{
return false;
}
}
fs.Close();
#endregion
return true;
}
public void ReceiveFile(string directoryPath,int bufferSize)
{
//先接收头包 以得到文件名和文件长度
byte [] packetFirst = pt.ReceiveOnePacket(4);//根据4字节包头指定长度接收头包
string rec = DropHead4(packetFirst);//去掉包头得到头包字符串信息
rec = rec.Remove(0, 1);//去掉最前的分隔线
rec = rec.Remove(rec.Length - 1, 1);//去掉最后的分隔线
string[] fileds = rec.Split(new string[] { "|" }, StringSplitOptions.None);//得到数据字段
string fileName = fileds[0];
string fileFullPath = directoryPath + fileds[0];
int fileLength = int.Parse(fileds[1]);
FileStream fs = new FileStream(fileFullPath, FileMode.Create, FileAccess.ReadWrite);
//循环接收文件内容
int receiveLength = fileLength; //需要接收的文件总字节数
byte[] recBufs = new byte[bufferSize]; //接收缓存
while (receiveLength > 0)
{
recBufs = pt.ReceiveLength(recBufs.Length);
if (receiveLength > recBufs.Length)
{
fs.Write(recBufs, 0, recBufs.Length);
}
else
{
fs.Write(recBufs, 0, receiveLength);
}
fs.Flush();
receiveLength -= recBufs.Length;
}
fs.Close();
}