C# Socket学习笔记三
客户端进行异步操作
接收信息及发送信息分开进行,运行多线程进行管理
主要代码发下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
// 实现Socket客户端的连接通信逻辑。
internal sealed class SocketClient : IDisposable
{
// Socket操作常数。
private const Int32 ReceiveOperation = 1, SendOperation = 0;
// 用于发送/接收消息的Socket。
private Socket clientSocket;
// Socket连接标志。
private Boolean connected = false;
// 侦听者端点。
private IPEndPoint hostEndPoint;
//缓冲区大小
private int bufferSize = 2048;
private int ReceiveBufferSize = 2096;
// 触发连接。
private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false);
// 触发发送/接收操作。
private static AutoResetEvent autoSendEvent = new AutoResetEvent(false);
private static AutoResetEvent autoReceiveEvent = new AutoResetEvent(false);
//private static AutoResetEvent[] autoSendReceiveEvents = new AutoResetEvent[] { new AutoResetEvent(false), new AutoResetEvent(false) };
// 创建一个未初始化的客户端实例。
// 启动传送/接收处理将调用Connect方法,然后是SendReceive方法。
internal SocketClient(String hostName, Int32 port)
{
// 获取主机有关的信息。
IPHostEntry host = Dns.GetHostEntry(hostName);
// 主机地址。
IPAddress[] addressList = host.AddressList;
// 实例化端点和Socket。
hostEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);
clientSocket = new Socket(hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
//得到连接服务器的状态
internal bool GetConnectState()
{
return connected;
}
// 连接主机(同步连接)。
internal void Connect()
{
try
{
clientSocket.Connect(hostEndPoint);
this.connected = true;
}
catch (SocketException ex)
{
throw new Exception(ex.Message);
}
}
//********* 以下为异步连接操作********
internal void ConnectAsync()
{
SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
connectArgs.UserToken = clientSocket;
connectArgs.RemoteEndPoint = hostEndPoint;
connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);
clientSocket.ConnectAsync(connectArgs);
autoConnectEvent.WaitOne();
SocketError errorCode = connectArgs.SocketError;
if (errorCode != SocketError.Success)
{
throw new SocketException((Int32)errorCode);
}
}
// 与主机断开连接。
internal void Disconnect()
{
clientSocket.Disconnect(false);
}
// 连接操作的回调方法
private void OnConnect(object sender, SocketAsyncEventArgs e)
{
// 发出连接完成信号。
autoConnectEvent.Set();
// 设置Socket已连接标志。
connected = (e.SocketError == SocketError.Success);
}
// 接收操作的回调方法
private void OnReceive(object sender, SocketAsyncEventArgs e)
{
// 发出接收完成信号。
//autoSendReceiveEvents[ReceiveOperation].Set();
autoReceiveEvent.Set();
}
// 发送操作的回调方法
private void OnSend(object sender, SocketAsyncEventArgs e)
{
// 发出发送完成信号。
//autoSendReceiveEvents[SendOperation].Set();
autoSendEvent.Set();
//if (e.SocketError == SocketError.Success)
//{
// if (e.LastOperation == SocketAsyncOperation.Send)
// {
// // 准备接收。
// Socket s = e.UserToken as Socket;
// byte[] receiveBuffer = new byte[1024];
// e.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
// e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
// s.ReceiveAsync(e);
// }
//}
//else
//{
// ProcessError(e);
//}
}
// 失败时关闭Socket,根据SocketError抛出异常。
private void ProcessError(SocketAsyncEventArgs e)
{
Socket s = e.UserToken as Socket;
if (s.Connected)
{
// 关闭与客户端关联的Socket
try
{
s.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
// 如果客户端处理已经关闭,抛出异常
}
finally
{
if (s.Connected)
{
s.Close();
}
}
}
// 抛出SocketException
throw new SocketException((Int32)e.SocketError);
}
//接收消息
internal string FromHsMessage()
{
if (connected)
{
// 创建一个接收缓冲区。
byte[] receiveBuffer = new byte[ReceiveBufferSize];
// 准备发送/接收操作的参数。
SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
completeArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
completeArgs.UserToken = clientSocket;
completeArgs.RemoteEndPoint = hostEndPoint;
completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
// 开始异步接收。
clientSocket.ReceiveAsync(completeArgs);
// 等待发送/接收完成。
autoReceiveEvent.WaitOne();
//AutoResetEvent.WaitAll(autoSendReceiveEvents);
// 从SocketAsyncEventArgs缓冲区返回数据.
return Encoding.UTF8.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred);
}
else
{
throw new SocketException((Int32)SocketError.NotConnected);
}
}
// 与主机交换消息(发送消息)。
internal String SendMessage(String message)
{
if (connected)
{
// 创建一个发送缓冲区。
Byte[] sendBuffer = Encoding.UTF8.GetBytes(message.ToCharArray(), 0, message.ToCharArray().Length);
// 准备发送/接收操作的参数。
SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
completeArgs.SetBuffer(sendBuffer, 0, bufferSize > sendBuffer.Length ? sendBuffer.Length : bufferSize);
completeArgs.UserToken = clientSocket;
completeArgs.RemoteEndPoint = hostEndPoint;
completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);
// 开始异步发送。
clientSocket.SendAsync(completeArgs);
// 等待发送/接收完成。
autoSendEvent.WaitOne();
//AutoResetEvent.WaitAll(autoSendReceiveEvents);
// 从SocketAsyncEventArgs缓冲区返回数据.
return Encoding.UTF8.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred);
}
else
{
throw new SocketException((Int32)SocketError.NotConnected);
}
}
#region IDisposable Members
// 释放SocketClient实例。
public void Dispose()
{
autoConnectEvent.Close();
autoSendEvent.Close();
autoReceiveEvent.Close();
//autoSendReceiveEvents[SendOperation].Close();
//autoSendReceiveEvents[ReceiveOperation].Close();
if (clientSocket.Connected)
{
clientSocket.Close();
}
}
#endregion
}