写在最前:以前在C\C++控制台,简单MFC和C#程序里简单接触了网络套接字编程。了解了网络套接字是这样一个流程 打开 -> 发送/接收->关闭 的简单过程。由于网络传输速度影响,在网络套接字的同步调用时会对程序的使用性产生影响(程序界面被卡死),后来知道可以使用异步编程的概念——通过开线程来达到不阻塞用户界面的效果。后来在接触网络套接字编程的次数多了以后,在C#.NET环境中发现Socket竟然多出了两类方法 XXXXAsync 和 BeginXXXX / EndXXXX。接下来就用代码演示一下这两类方法如何使用~
接下来的页面会很长,能扯一点的现在这扯一点。这两类方法分别对应SocketAsyncEventArgs 、 IAsyncResult。我暂时也讲不出什么,有问题问吧还是。文章最后有如何在vs一个解决方案中调试启动多个项目(这可能是很多人没有注意到的操作)。
So long,Coding
首先是XXXXAsync的,
Server
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace SocketTest
{
class Program
{
static void Main(string[] args)
{
Socket serverSk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSk.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8596));
serverSk.Listen(1);
SocketAsyncEventArgs AcceptSAE = new SocketAsyncEventArgs();
AcceptSAE.Completed += new EventHandler(AcceptSAE_Completed);
serverSk.AcceptAsync(AcceptSAE);
Console.ReadLine();
}
static void AcceptSAE_Completed(object sender, SocketAsyncEventArgs e)
{
Socket serverSk = sender as Socket;
if (e.SocketError == SocketError.Success)
{
serverSk = e.AcceptSocket;
SocketAsyncEventArgs SendSAE = new SocketAsyncEventArgs();
byte[] data = System.Text.Encoding.UTF8.GetBytes("OK,Just Put IT!");
SendSAE.SetBuffer(data, 0, data.Length);
SendSAE.Completed += new EventHandler(SendSAE_Completed);
SocketAsyncEventArgs RecieveSAE = new SocketAsyncEventArgs();
byte[] buffer = new byte[2048];//因为我们不知道上面的字符串究竟会场生多少字节,这里我们就设置一个理论上可以满足大小的值2046。
RecieveSAE.SetBuffer(buffer, 0, buffer.Length);
RecieveSAE.Completed += new EventHandler(RecieveSAE_Completed);
serverSk.ReceiveAsync(RecieveSAE);
serverSk.SendAsync(SendSAE);
}
else
Console.WriteLine("接受网络套接字连接请求失败!具体原因请自己调试!");
}
static void RecieveSAE_Completed(object sender, SocketAsyncEventArgs e)
{
Socket sk = sender as Socket;
byte[] data = e.Buffer; //注意这里,如何取关联到套接字的发送接受的缓冲区中的值。
string msg = System.Text.Encoding.UTF8.GetString(data);
Console.WriteLine("Message received: " + msg);
// sk.DisconnectAsync();//你看看 该怎么做呢?
}
static void SendSAE_Completed(object sender, SocketAsyncEventArgs e)
{
Socket sk = sender as Socket;
if (e.SocketError == SocketError.Success)
{
Console.WriteLine("Send complete!");
byte[] data = e.Buffer; //注意这里,如何取关联到套接字的发送接受的缓冲区中的值。
string msg = System.Text.Encoding.UTF8.GetString(data);
Console.WriteLine("What you sent: " + msg);
}
}
}
}
Client:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace SocketTestTwo
{
class Program
{
static void Main(string[] args)
{
Socket clientSk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs ConnectSAE = new SocketAsyncEventArgs();
ConnectSAE.RemoteEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8596);
ConnectSAE.Completed += new EventHandler(ConnectSAE_Completed);
clientSk.ConnectAsync(ConnectSAE);
Console.ReadLine();
}
static void ConnectSAE_Completed(object sender, SocketAsyncEventArgs e)
{
Socket clientSk = sender as Socket;
if (e.SocketError == SocketError.Success && clientSk.Connected)
{
SocketAsyncEventArgs SendSAE = new SocketAsyncEventArgs();
byte[] data = System.Text.Encoding.UTF8.GetBytes("I want put all funy things together!");
SendSAE.SetBuffer(data, 0, data.Length);
SendSAE.Completed += new EventHandler(SendSAE_Completed);
SocketAsyncEventArgs RecieveSAE = new SocketAsyncEventArgs();
byte[] buffer = new byte[2048];//因为我们不知道上面的字符串究竟会场生多少字节,这里我们就设置一个理论上可以满足大小的值2046。
RecieveSAE.SetBuffer(buffer, 0, buffer.Length);
RecieveSAE.Completed += new EventHandler(RecieveSAE_Completed);
//先调用异步接收,再调用异步发送。让你体验到异步明显非一般的感觉。
clientSk.ReceiveAsync(RecieveSAE);
clientSk.SendAsync(SendSAE);
}
}
static void RecieveSAE_Completed(object sender, SocketAsyncEventArgs e)
{
Socket sk = sender as Socket;
byte[] data = e.Buffer; //注意这里,如何取关联到套接字的发送接受的缓冲区中的值。
string msg = System.Text.Encoding.UTF8.GetString(data);
Console.WriteLine("Message received: "+msg);
//sk.DisconnectAsync();//你看看 该怎么做呢?
}
static void SendSAE_Completed(object sender, SocketAsyncEventArgs e)
{
Socket sk = sender as Socket;
if (e.SocketError == SocketError.Success)
{
Console.WriteLine("Send complete!");
}
}
}
}
然后是BenginXXXX 和 EndXXXX的
Server
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace SocketTestt
{
public class MyObject
{
#region 类字段
private Socket _Socket;
private string _MyName = "";
private byte[] _Buffer;
#endregion
#region 类属性
public Socket Socket
{
get { return _Socket; }
set { _Socket = value; }
}
public byte[] Buffer
{
get { return _Buffer; }
set { _Buffer = value; }
}
public string MyName
{
get { return _MyName; }
set { _MyName = value; }
}
#endregion
#region 构造函数
public MyObject(Socket socket, string myName)
{
_Socket = socket;
_MyName = myName;
}
public MyObject(Socket socket, string myName,byte[] buffer)
{
_Socket = socket;
_MyName = myName;
_Buffer = buffer;
}
#endregion
}
class Program
{
static void Main(string[] args)
{
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8596));
server.Listen(1);
server.BeginAccept(new AsyncCallback(AcceptComplete),new MyObject(server,"开始连接了"));
Console.ReadLine();
}
static void AcceptComplete(IAsyncResult ar)
{
MyObject myObj = ar.AsyncState as MyObject;
Socket serverSk = myObj.Socket.EndAccept(ar);
byte[] buffer = new byte[2048]; //虽然不知道会收到多少,但是多了总比少了好。
serverSk.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(RecievedComplete), new MyObject(serverSk, "开始接收了", buffer));
byte[] datas = System.Text.Encoding.UTF8.GetBytes("I know , Just put it!");
serverSk.BeginSend(datas, 0, datas.Length, SocketFlags.None, new AsyncCallback(SendComplete), new MyObject(serverSk, "开始发送了", datas));
}
static void SendComplete(IAsyncResult ar)
{
MyObject myObj = ar.AsyncState as MyObject;
Socket sk = myObj.Socket;
int sended = sk.EndSend(ar);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(myObj.Buffer));
}
static void RecievedComplete(IAsyncResult ar)
{
MyObject myObj = ar.AsyncState as MyObject;
Socket sk = myObj.Socket;
int recieved = sk.EndReceive(ar);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(myObj.Buffer));
}
}
}
Client
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace SocketTwo
{
public class MyObject
{
#region 类字段
private Socket _Socket;
private string _MyName = "";
private byte[] _Buffer;
#endregion
#region 类属性
public Socket Socket
{
get { return _Socket; }
set { _Socket = value; }
}
public byte[] Buffer
{
get { return _Buffer; }
set { _Buffer = value; }
}
public string MyName
{
get { return _MyName; }
set { _MyName = value; }
}
#endregion
#region 构造函数
public MyObject(Socket socket, string myName)
{
_Socket = socket;
_MyName = myName;
}
public MyObject(Socket socket, string myName, byte[] buffer)
{
_Socket = socket;
_MyName = myName;
_Buffer = buffer;
}
#endregion
}
class Program
{
static void Main(string[] args)
{
Socket clientSk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSk.BeginConnect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8596), new AsyncCallback(ConnectComplete), new MyObject(clientSk, "开始连接了"));
Console.ReadLine();
}
static void ConnectComplete(IAsyncResult ar)
{
MyObject myObj = ar.AsyncState as MyObject;
Socket clientSk = myObj.Socket;
byte[] datas = System.Text.Encoding.UTF8.GetBytes("I always want put things together!");
clientSk.BeginSend(datas, 0, datas.Length, SocketFlags.None, new AsyncCallback(SendComplete), new MyObject(clientSk, "开始发送了", datas));
byte[] buffer = new byte[2048]; //虽然不知道会收到多少,但是多了总比少了好。
clientSk.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(RecievedComplete), new MyObject(clientSk, "开始接收了", buffer));
}
static void SendComplete(IAsyncResult ar)
{
MyObject myObj = ar.AsyncState as MyObject;
Socket sk = myObj.Socket;
int sended = sk.EndSend(ar);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(myObj.Buffer));
}
static void RecievedComplete(IAsyncResult ar)
{
MyObject myObj = ar.AsyncState as MyObject;
Socket sk = myObj.Socket;
int recieved = sk.EndReceive(ar);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(myObj.Buffer));
}
}
}
The end.
附:
启动第一个项目
启动第二个...第N个
代码下载: