在(三)中我们用多线程简单实现了异步,这里用微软为我们提供的IAsyncResult模式来实现
现在代码增多了,把处理套接字的部分单独创建一个类SocketServer
代码如下,同时仍然保留了同步的Listen方法,这里异步的监听命名为AsyncListen
class
SocketServer

...
{
private int _port;
private string _ip;
private string _hostName;
private int _backlog; //队列连接数

private IPEndPoint ipEndPoint;
private IPAddress ipAddress;
private IPHostEntry ipHostEntry;
private Socket listener;

public int Port

...{

get ...{ return _port; }

set ...{ _port = value; }
}
public int BackLog

...{

get ...{ return _backlog; }

set ...{ _backlog = value; }
}
public string IP

...{

get ...{ return _ip; }

set ...{ _ip = value; }
}
public string HostName

...{

get ...{ return _hostName; }

set ...{ _hostName = value; }
}


public UploadServer()

...{
listener = null;
_ip = "127.0.0.1";
_port = 7788;
_backlog = 10;
_hostName = String.Empty;
}


/**//// <summary>
/// 初始化服务器地址
/// </summary>
private void InitIPInfo()

...{
if (_ip == String.Empty)

...{
if (_hostName != String.Empty)

...{
ipHostEntry = Dns.GetHostEntry(_hostName);
ipAddress = ipHostEntry.AddressList[0];
}
else

...{
throw new Exception("未指定有效服务器地址");
}
}
else

...{
ipAddress = IPAddress.Parse(_ip);
ipHostEntry = Dns.GetHostEntry(ipAddress);
}
ipEndPoint = new IPEndPoint(ipAddress, _port);
}

public void Listen()

...{
InitIPInfo();
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(_backlog);
Console.WriteLine("服务启动,开始监听");
Console.WriteLine("等待客户端连接...");

Socket clientSocket = listener.Accept();
Console.WriteLine("建立连接");

// 接受数据
byte[] buffer = new byte[1024];
clientSocket.Receive(buffer);
Console.WriteLine("接受客户端信息:{0}", Encoding.GetEncoding("gb2312").GetString(buffer));
//回复客户端
byte[] backBuffer = new byte[1024];
string backString = "收到数据";

backBuffer = Encoding.GetEncoding("gb2312").GetBytes(backString);
clientSocket.Send(backBuffer);

clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
Console.WriteLine("关闭客户端连接");
}

public void AsyncListen()

...{
InitIPInfo();

listener = new Socket(ipEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

listener.Bind(ipEndPoint);
listener.Listen(_backlog);

Console.WriteLine("服务启动,开始监听");
Console.WriteLine("等待客户端连接...");

listener.BeginAccept(new AsyncCallback(acceptCallback), listener);
}

private void acceptCallback(IAsyncResult ar)

...{
Socket listener = (Socket)ar.AsyncState;
Socket clientSocket = listener.EndAccept(ar); //获得客户端套接字接口
Console.WriteLine("建立连接");

StateObject state = new StateObject();
state.WorkSocket = clientSocket;
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(readCallback), state); //开始接受数据
}

public class StateObject

...{
public Socket WorkSocket = null;
public static int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
}

//结束挂起的异步读取
public static void readCallback(IAsyncResult ar)

...{
StateObject state = (StateObject)ar.AsyncState;
Socket clientSocket = state.WorkSocket;

if (clientSocket.Connected)

...{
int read = clientSocket.EndReceive(ar);//结束挂起的异步读取


//一直接受数据到没有为止
if (read > 0)

...{
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(readCallback), state);
}

Console.WriteLine("接受客户端信息:{0}", Encoding.GetEncoding("gb2312").GetString(state.buffer));
//回复客户端
byte[] backBuffer = new byte[1024];
string backString = "收到数据";

backBuffer = Encoding.GetEncoding("gb2312").GetBytes(backString);
clientSocket.Send(backBuffer);
clientSocket.Close();
}
else

...{
Console.WriteLine("连接已经关闭!");
}
}

}
在Program.cs如下调用
SocketServer us = new SocketServer();
us.AsyncListen();
OK运行查看效果

上面的例子基本实现,实际存在问题还很多
比如
如果客户端传送的数据一次接受不完
没有服务器端向客户端发送信息
而且判断是否接受完客户端数据上面的例子也有问题,下面来完善一下
class
SocketServer

...
{
private int _port;
private string _ip;
private string _hostName;
private int _backlog; //队列连接数

private IPEndPoint ipEndPoint;
private IPAddress ipAddress;
private IPHostEntry ipHostEntry;
private Socket listener;

private static ManualResetEvent allDone = new ManualResetEvent(false);

public int Port

...{

get ...{ return _port; }

set ...{ _port = value; }
}
public int BackLog

...{

get ...{ return _backlog; }

set ...{ _backlog = value; }
}
public string IP

...{

get ...{ return _ip; }

set ...{ _ip = value; }
}
public string HostName

...{

get ...{ return _hostName; }

set ...{ _hostName = value; }
}

public class StateObject

...{
public Socket WorkSocket = null;
public static int BufferSize = 2;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}

public SocketServer()

...{
listener = null;
_ip = "127.0.0.1";
_port = 7788;
_backlog = 10;
_hostName = String.Empty;

}


/**//// <summary>
/// 初始化服务器地址
/// </summary>
private void InitIPInfo()

...{
if (_ip == String.Empty)

...{
if (_hostName != String.Empty)

...{
ipHostEntry = Dns.GetHostEntry(_hostName);
ipAddress = ipHostEntry.AddressList[0];
}
else

...{
throw new Exception("未指定有效服务器地址");
}
}
else

...{
ipAddress = IPAddress.Parse(_ip);
ipHostEntry = Dns.GetHostEntry(ipAddress);
}
ipEndPoint = new IPEndPoint(ipAddress, _port);
}

public void Listen()

...{
InitIPInfo();
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(_backlog);
Console.WriteLine("服务启动,开始监听");
Console.WriteLine("等待客户端连接...");

Socket clientSocket = listener.Accept();
Console.WriteLine("建立连接");

// 接受数据
byte[] buffer = new byte[1024];
clientSocket.Receive(buffer);
Console.WriteLine("接受客户端信息:{0}", Encoding.GetEncoding("gb2312").GetString(buffer));
//回复客户端
byte[] backBuffer = new byte[1024];
string backString = "收到数据";

backBuffer = Encoding.GetEncoding("gb2312").GetBytes(backString);
clientSocket.Send(backBuffer);

clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
Console.WriteLine("关闭客户端连接");
}

public void AsyncListen()

...{
InitIPInfo();

listener = new Socket(ipEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

try

...{
listener.Bind(ipEndPoint);
listener.Listen(_backlog);

Console.WriteLine("服务启动,开始监听");
Console.WriteLine("等待客户端连接...");
while (true)

...{
allDone.Reset();
listener.BeginAccept(new AsyncCallback(acceptCallback), listener);
allDone.WaitOne();
}
}
catch (Exception ex)

...{
Console.WriteLine("发生错误:"+ex.Message);
}
}

private void acceptCallback(IAsyncResult ar)

...{
Console.WriteLine("acceptCallback 被调用");
Socket listener = (Socket)ar.AsyncState;
Socket clientSocket = listener.EndAccept(ar); //获得客户端套接字接口
Console.WriteLine("建立连接");
allDone.Set();

StateObject state = new StateObject();
state.WorkSocket = clientSocket;
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(readCallback), state); //开始接受数据

}

public void readCallback(IAsyncResult ar)

...{
StateObject state = (StateObject)ar.AsyncState;
Socket clientSocket = state.WorkSocket;

try

...{
int read = 0;
read = clientSocket.EndReceive(ar);//结束挂起的异步读取

if (read > 0)

...{
state.sb.Append(Encoding.GetEncoding("gb2312").GetString(state.buffer, 0, read));
Console.WriteLine(state.sb.ToString());

if (state.sb.ToString().IndexOf("<end>") > -1)

...{

Console.WriteLine("已经接收完数据");
//回复客户端
byte[] backBuffer = new byte[1024];
string backString = "已经收到数据";

backBuffer = Encoding.GetEncoding("gb2312").GetBytes(backString);
clientSocket.BeginSend(backBuffer, 0, backBuffer.Length, SocketFlags.None, new AsyncCallback(SendCallback), state);
}
else

...{
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(readCallback), state);
}
}
}
catch (SocketException se)

...{
if (se.ErrorCode == 10054)

...{
Console.WriteLine("客户端已断开连接!");
}
else

...{
Console.WriteLine(se.Message);
}
}
catch (Exception ex)

...{
Console.WriteLine(ex.Message);
}

}

private void SendCallback(IAsyncResult ar)

...{
Console.WriteLine("SendCallback 被调用");
try

...{
StateObject state = (StateObject)ar.AsyncState;
Socket handle = state.WorkSocket;
int bytesSent = handle.EndSend(ar);
Console.WriteLine("发送到客户端 {0}", bytesSent);
Console.WriteLine("接受客户端信息:{0}",state.sb.ToString() );
handle.Shutdown(SocketShutdown.Both);
handle.Close();

}
catch (Exception e)

...{
Console.WriteLine(e.ToString());
}
}

}
这里判断客户端传送数据是否接受完成时个比较麻烦的问题
这里在客户端传入的字符串中用了<end>标志来判断
如果使用EndReceive的返回值是否大于1来判断会出现无法调用委托方法的情况也不报错
因为当没有数据传输到服务器端的时候BeginReceive并不会调用委托
自己感觉靠添加额外定制符号的办法不是很让人舒服,暂时也没有其他好的解决办法,如果有朋友知道告诉我一下哈:)
下面贴出客户端修改为异步以后的代码
public
class
StateObject

...
{
public Socket workSocket = null;
public static int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}


class
SocketClient

...
{
private int _port;
private string _ip;
private string _hostName;

private IPEndPoint ipEndPoint;
private IPAddress ipAddress;
private IPHostEntry ipHostEntry;

private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
private static String response = String.Empty; //服务器返回的信息

public int Port

...{

get ...{ return _port; }

set ...{ _port = value; }
}
public string IP

...{

get ...{ return _ip; }

set ...{ _ip = value; }
}
public string HostName

...{

get ...{ return _hostName; }

set ...{ _hostName = value; }
}

private void InitIPInfo()

...{
if (_ip == String.Empty)

...{
if (_hostName != String.Empty)

...{
ipHostEntry = Dns.GetHostEntry(_hostName);
ipAddress = ipHostEntry.AddressList[0];
}
else

...{
throw new Exception("未指定有效服务器地址");
}
}
else

...{
ipAddress = IPAddress.Parse(_ip);
ipHostEntry = Dns.GetHostEntry(ipAddress);
}
ipEndPoint = new IPEndPoint(ipAddress, _port);
}

public UploadClient()

...{
_ip = "127.0.0.1";
_port = 7788;
_hostName = String.Empty;
}

public void Connect()

...{
InitIPInfo();

try

...{

/**////创建socket并连接到服务器
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine("等待连接…");
serverSocket.Connect(ipEndPoint);//连接到服务器
Console.WriteLine("已连接");

//发送数据
byte[] buffer = new byte[1024];
buffer = Encoding.GetEncoding("gb2312").GetBytes("Godling is a good man!<end>");
serverSocket.Send(buffer);

//接受数据
byte[] bufferGet = new byte[1024];
serverSocket.Receive(bufferGet);
Console.WriteLine("接受服务端信息:{0}", Encoding.GetEncoding("gb2312").GetString(bufferGet));

serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();

}
catch (ArgumentNullException e)

...{
Console.WriteLine("argumentNullException: {0}", e);
}
catch (SocketException e)

...{
Console.WriteLine("SocketException:{0}", e);
}

Console.WriteLine("Press Enter to Exit");
}

//开始异步连接
public void AsyncConnect()

...{
try

...{
InitIPInfo();

Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallback), serverSocket);
connectDone.WaitOne(); //阻止运行直到连接成功

//发送数据
string data = "你能收到我吗?<end>";
byte[] byteData = Encoding.GetEncoding("gb2312").GetBytes(data);
serverSocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), serverSocket);
sendDone.WaitOne();


StateObject state = new StateObject();
state.workSocket = serverSocket;
serverSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
receiveDone.WaitOne();
Console.WriteLine("接收到服务器信息:{0}", response);

serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();
}
catch(Exception ex)

...{
Console.WriteLine("发生异常"+ex.Message);
}

}

// 连接完成回调方法
private void ConnectCallback(IAsyncResult ar)

...{
try

...{
Socket serverSocket = (Socket)ar.AsyncState;
serverSocket.EndConnect(ar);
Console.WriteLine("已连接到{0}",serverSocket.RemoteEndPoint.ToString());

connectDone.Set();
}
catch (Exception e)

...{
Console.WriteLine("连接错误!"+e.ToString());
}

}

// 数据发送回调方法
private static void SendCallback(IAsyncResult ar)

...{
try

...{
Socket serverSocket = (Socket)ar.AsyncState;
int bytesSent = serverSocket.EndSend(ar);
Console.WriteLine("向服务器发送数据 {0} bytes", bytesSent);

sendDone.Set();
}
catch (Exception e)

...{
Console.WriteLine(e.ToString());
}
}

// 接收数据回调方法
private static void ReceiveCallback(IAsyncResult ar)

...{
StateObject state = (StateObject)ar.AsyncState;
Socket serverSocket = state.workSocket;

int read = 0;

if (serverSocket.Connected)

...{
read = serverSocket.EndReceive(ar);
}
if (read > 0)

...{
state.sb.Append(Encoding.GetEncoding("gb2312").GetString(state.buffer, 0, read));
try

...{
serverSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
}
catch (SocketException se)

...{
if (se.ErrorCode == 10054)

...{
Console.WriteLine("远程主机已经断开连接!");
}
}
}
else

...{
if (state.sb.Length > 1)

...{
response = state.sb.ToString();
}
receiveDone.Set();
}
}




}