建议先学会C#同步通讯(阻断式),再来看异步通讯
同步通讯简例:C#搭建Socket服务器与客户端,助你快速入门(极简版)
在开始看代码前,请先捋清楚异步通讯实现的思路。
目录
一、对于服务器端
思路
服务器在绑定好端口后要:
1、先BeginAccept,开始等待客户端接入
2、在EndAccept,有客户端接入之后;要BeginReceive,开始等待接收客户端请求。
3、在EndReceive,接收到客户端请求后;要BeginSend,开始发送相关信息。
4、在EndSend,发送完一次信息后;要BeginReceive,再次开始等待接收客户端请求。
上面4个步骤能够实现一个客户端多次请求。
如果想要实现多个客户端多次请求,那么在第2步EndAccept,有客户端接入之后;还要BeginAccept,开始等待下一个客户端接入。
代码部分
捋清楚上述思路后,请看代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace ServerAsy
{
class Program
{
static byte[] buffer;
static void Main(string[] args)
{
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
EndPoint endpoint = new IPEndPoint(IPAddress.Parse("10.206.234.113"), 6000);
server.Bind(endpoint);
server.Listen(10); // 和同步通讯一样,server只是负责监听
Console.WriteLine("端口绑定成功,开始监听......");
// 客户端连接后,执行AcceptCallback方法内的代码,server是传递给AcceptCallback方法的参数,其他类似的代码同理
server.BeginAccept(AcceptCallback, server);
Console.ReadKey();
}
private static void AcceptCallback(IAsyncResult ar)
{
// try catch是为了防止客户端断开连接后,服务器报错,用了之后只是会打印错误信息,服务器程序还在
try
{
Socket server = ar.AsyncState as Socket; // 这一行代码是在获取传入的参数
Socket serverManager = server.EndAccept(ar); // 和同步通讯一样,要将server监听到的客户端交给serverManager处理,进行后续收发消息操作。
buffer = new byte[serverManager.ReceiveBufferSize]; // 定义buffer的长度为serverManager实际接收到的字节长度
serverManager.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, serverManager);
Console.WriteLine("已有客户端连接,等待接收请求......");
server.BeginAccept(AcceptCallback, server);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
Socket serverManager = ar.AsyncState as Socket;
int length = serverManager.EndReceive(ar);
// 将客户端发来的byte[]转换为字符串
string content = Encoding.UTF8.GetString(buffer, 0, length);
Console.WriteLine("收到了客户端的请求:" + content);
// 将要回复的内容转换为byte[]
string reply = "这里是服务器";
byte[] data = Encoding.UTF8.GetBytes(reply);
serverManager.BeginSend(data, 0, data.Length, SocketFlags.None, SendCallback, serverManager);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void SendCallback(IAsyncResult ar)
{
Socket serverManager = ar.AsyncState as Socket;
serverManager.EndSend(ar);
serverManager.BeginReceive(buffer, 0, serverManager.ReceiveBufferSize, SocketFlags.None, ReceiveCallback, serverManager);
}
}
二、对于客户端
思路
1、客户端先BeginConnect,开始连接服务器
2、在EndConnect,连接服务器成功后;要BeginSend开始发送请求
3、在EndSend请求发送完毕后;要BeginReceive,开始接收回复
4、在EndReceive,收到回复后,将收到的字节数组进行转换
上述4个步骤实现了客户端发送一次请求,想要多次发送请求,需要while(true)
由于我是用控制台应用写的,因此在代码部分我就不用BeginConnect进行连接了,否则异步方法不阻塞,直接就退出程序了。
代码部分
捋清上述思路后,请看代码
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace ClientAsy
{
class Program
{
static byte[] buffer;
static void Main(string[] args)
{
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
EndPoint endpoint = new IPEndPoint(IPAddress.Parse("10.206.234.113"), 6000);
client.Connect(endpoint);
buffer = new byte[client.ReceiveBufferSize];
Console.WriteLine("连接成功");
while (true)
{
string mes = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(mes);
client.BeginSend(data, 0, data.Length, SocketFlags.None, SendCallback, client);
}
}
private static void SendCallback(IAsyncResult ar)
{
Socket client = ar.AsyncState as Socket;
client.EndSend(ar);
client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, client);
}
private static void ReceiveCallback(IAsyncResult ar)
{
Socket client = ar.AsyncState as Socket;
int length = client.EndReceive(ar);
string mes = Encoding.UTF8.GetString(buffer, 0, length);
Console.WriteLine(mes);
}
}
}