本文参考了http://www.codeproject.com/KB/IP/socketasynceventargssampl.aspx
作了一些修改
在.NET 2.0 SP1上可以使用SocketAsyncEventArgs类,本文的代码就是用Microsoft Visual Studio .NET 2005编写的。

Code
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SocketAsyncClient


{

/**//// <summary>
/// socket客户端
/// 异步实现
/// </summary>
public sealed class SocketClient : IDisposable

{

/**//// <summary>
/// Constants for socket operations.
/// </summary>
private const Int32 ReceiveOperation = 1, SendOperation = 0;


/**//// <summary>
/// The socket used to send/receive messages.
/// </summary>
private Socket clientSocket;


/**//// <summary>
/// Flag for connected socket.
/// </summary>
private Boolean connected = false;
public Boolean Connected

{

get
{ return connected; }
}



/**//// <summary>
/// Listener endpoint.
/// </summary>
private IPEndPoint hostEndPoint;


/**//// <summary>
/// Signals a connection.
/// </summary>
private AutoResetEvent autoConnectEvent = new AutoResetEvent(false);
// private static AutoResetEvent autoConnectEvent = new AutoResetEvent(false);


/**//// <summary>
/// Signals the send/receive operation.
/// </summary>
// private static AutoResetEvent[] autoSendReceiveEvents = new AutoResetEvent[]
private AutoResetEvent[] autoSendReceiveEvents = new AutoResetEvent[]

{
new AutoResetEvent(false),
new AutoResetEvent(false)
};


/**//// <summary>
/// Create an uninitialized client instance.
/// To start the send/receive processing
/// call the Connect method followed by SendReceive method.
/// </summary>
/// <param name="hostName">Name of the host where the listener is running.</param>
/// <param name="port">Number of the TCP port from the listener.</param>
public SocketClient(String hostName, Int32 port)

{
// Get host related information.
IPHostEntry host = Dns.GetHostEntry(hostName);

// Addres of the host.
IPAddress[] addressList = host.AddressList;

// Instantiates the endpoint and socket.
this.hostEndPoint = new IPEndPoint(addressList[addressList.Length - 1], port);
this.clientSocket = new Socket(this.hostEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

}


/**//// <summary>
/// Connect to the host.
/// </summary>
/// <returns>True if connection has succeded, else false.</returns>
public void Connect()

{
SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();

connectArgs.UserToken = this.clientSocket;
connectArgs.RemoteEndPoint = this.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);
}

}


/**//// <summary>
/// Disconnect from the host.
/// </summary>
public void Disconnect()

{
clientSocket.Disconnect(false);
}

private void OnConnect(object sender, SocketAsyncEventArgs e)

{
// Signals the end of connection.
autoConnectEvent.Set();

// Set the flag for socket connected.
this.connected = (e.SocketError == SocketError.Success);
}

private void OnReceive(object sender, SocketAsyncEventArgs e)

{
// Signals the end of receive.
autoSendReceiveEvents[SendOperation].Set();
}

private void OnSend(object sender, SocketAsyncEventArgs e)

{
// Signals the end of send.
autoSendReceiveEvents[ReceiveOperation].Set();

if (e.SocketError == SocketError.Success)

{
if (e.LastOperation == SocketAsyncOperation.Send)

{
// Prepare receiving.
Socket s = e.UserToken as Socket;

byte[] receiveBuffer = new byte[255];
e.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
e.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);

s.ReceiveAsync(e);


// Encoding.ASCII.GetString(s..Buffer, completeArgs.Offset, completeArgs.BytesTransferred);

}
}
else

{
this.ProcessError(e);
}
}



/**//// <summary>
/// Close socket in case of failure and throws a SockeException according to the SocketError.
/// </summary>
/// <param name="e">SocketAsyncEventArg associated with the failed operation.</param>
private void ProcessError(SocketAsyncEventArgs e)

{
Socket s = e.UserToken as Socket;
if (s.Connected)

{
// close the socket associated with the client
try

{
s.Shutdown(SocketShutdown.Both);
}
catch (Exception)

{
// throws if client process has already closed
}
finally

{
if (s.Connected)

{
s.Close();
}
}
}

// Throw the SocketException
throw new SocketException((Int32)e.SocketError);
}


/**//// <summary>
/// Exchange a message with the host.
/// </summary>
/// <param name="message">Message to send.</param>
/// <returns>Message sent by the host.</returns>
public String SendReceive(String message)

{
//指示应挂起此线程以使其他等待线程能够执行
System.Threading.Thread.Sleep(0);
if (this.connected)

{
// Create a buffer to send.
Byte[] sendBuffer = Encoding.Default.GetBytes(message);
//StrHelper.Str2AscArr(message);

// Prepare arguments for send/receive operation.
SocketAsyncEventArgs completeArgs = new SocketAsyncEventArgs();
completeArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);
completeArgs.UserToken = this.clientSocket;
completeArgs.RemoteEndPoint = this.hostEndPoint;
completeArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);

// Start sending asyncronally.
clientSocket.SendAsync(completeArgs);

// Wait for the send/receive completed.
AutoResetEvent.WaitAll(autoSendReceiveEvents);
StringBuilder resultMsg = new StringBuilder();
resultMsg.Append(Encoding.Default.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred));

while ((completeArgs.UserToken as Socket).Available > 0)

{
clientSocket.ReceiveAsync(completeArgs);
AutoResetEvent.WaitAll(autoSendReceiveEvents);
resultMsg.Append(Encoding.Default.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred));
}

return resultMsg.ToString();


// return Encoding.ASCII.GetString(completeArgs.Buffer, completeArgs.Offset, completeArgs.BytesTransferred);


}
else

{
throw new SocketException((Int32)SocketError.NotConnected);
}
}


IDisposable Members#region IDisposable Members


/**//// <summary>
/// Disposes the instance of SocketClient.
/// </summary>
public void Dispose()

{
autoConnectEvent.Close();
autoSendReceiveEvents[SendOperation].Close();
autoSendReceiveEvents[ReceiveOperation].Close();
if (this.clientSocket.Connected)

{
this.clientSocket.Close();
}
}

#endregion
}
}
