您的位置:首页 > 理论基础 > 计算机网络

C#:一个增强的TcpClient(三)读取

2012-03-23 15:09 423 查看
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Splash.Net.Sockets
{
/// <summary>
/// 异步读状态对象
/// </summary>
internal class AsyncReadStateObject
{
public ManualResetEvent eventDone;
public NetworkStream stream;
public Exception exception;
public Int32 numberOfBytesRead;
}

/// <summary>
/// 实现TcpClient的异步接收
/// </summary>
public partial class TcpClientPlus
{
/// <summary>
/// 设置读超时等待值
/// </summary>
public Int32 ReadTimeout = Timeout.Infinite;

/// <summary>
/// 异步接收
/// </summary>
/// <param name="data">接收到的字节数组</param>
public void Read(out Byte[] data)
{
// 获取网络数据流
NetworkStream netStream = GetStream();

// 用户定义对象
AsyncReadStateObject State = new AsyncReadStateObject
{   // 将事件状态设置为非终止状态,导致线程阻止
eventDone = new ManualResetEvent(false),
stream = netStream,
exception = null,
numberOfBytesRead = -1
};

Byte[] Buffer = new Byte[ReceiveBufferSize];
using (MemoryStream memStream = new MemoryStream(ReceiveBufferSize))
{
Int32 TotalBytes = 0;       // 总共需要接收的字节数
Int32 ReceivedBytes = 0;    // 当前已接收的字节数
while (true)
{
// 将事件状态设置为非终止状态,导致线程阻止
State.eventDone.Reset();

// 异步读取网络数据流
netStream.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(AsyncReadCallback), State);

// 等待操作完成信号
if (State.eventDone.WaitOne(ReadTimeout, false))
{   // 接收到信号
if (State.exception != null) throw State.exception;

if (State.numberOfBytesRead == 0)
{   // 连接已经断开
throw new SocketException();
}
else if (State.numberOfBytesRead > 0)
{
if (TotalBytes == 0)
{   // 提取流头部字节长度信息
TotalBytes = BitConverter.ToInt32(Buffer, 0);

// 保存剩余信息
memStream.Write(Buffer, 4, State.numberOfBytesRead - 4);
}
else
{
memStream.Write(Buffer, 0, State.numberOfBytesRead);
}

ReceivedBytes += State.numberOfBytesRead;
if (ReceivedBytes >= TotalBytes) break;
}
}
else
{   // 超时异常
throw new TimeoutException();
}
}

// 将流内容写入字节数组
if (String.IsNullOrEmpty(_secretKey))
{
data = (memStream.Length > 0) ? memStream.ToArray() : null;
}
else
{   // 解密数据
data = (memStream.Length > 0) ? Decrypt(memStream.ToArray(), 0, TotalBytes - 4) : null;
}
}
}

/// <summary>
/// 异步接收
/// </summary>
/// <param name="answer">接收到的字符串</param>
/// <param name="codePage">代码页</param>
/// <remarks>
/// 代码页:
///     936:简体中文GB2312
///     54936:简体中文GB18030
///     950:繁体中文BIG5
///     1252:西欧字符CP1252
///     65001:UTF-8编码
/// </remarks>
public void Read(out String answer, Int32 codePage = 65001)
{
Byte[] data;
Read(out data);
answer = (data != null) ? Encoding.GetEncoding(codePage).GetString(data) : null;
}

/// <summary>
/// 异步读取回调函数
/// </summary>
/// <param name="ar">异步操作结果</param>
private static void AsyncReadCallback(IAsyncResult ar)
{
AsyncReadStateObject State = ar.AsyncState as AsyncReadStateObject;
try
{   // 异步写入结束
State.numberOfBytesRead = State.stream.EndRead(ar);
}

catch (Exception e)
{   // 异步连接异常
State.exception = e;
}

finally
{   // 将事件状态设置为终止状态,线程继续
State.eventDone.Set();
}
}
}
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息