C#中Socket通信编程的异步实现
2017-08-31 11:19
756 查看
什么是Socket编程的异步是实现
所谓Socket编程的异步实现是指按照异步过程来实现Socket编程,那么什么是异步过程呢,我们把在完成了一次调用后通过状态、通知和回调来告知调用者的方式成为异步过程,换句话说,在异步过程中当调用一个方法时,调用者并不能够立刻得到结果,只有当这个方法调用完毕后调用者才能获得调用结果。这样做的好处是什么呢?答案是高效。相信大家还记得我们在《C#中Socket通信编程的同步实现》这篇文章中使用多线程来实现简单聊天的案例吧,在这个案例中我们需要开启两个线程来不断监听客户端的连接和客户端的消息,这样的效率肯定是很低的。那么现在好了,我们可以通过异步过程来解决这个问题,下面我们就来看看如何实现Socket的异步通信。如何实现Socket异步通信
服务端
基本流程
创建套接字绑定套接字的IP和端口号——Bind()
使套接字处于监听状态等待客户端的连接请求——Listen()
当请求到来后,使用BeginAccept()和EndAccept()方法接受请求,返回新的套接字
使用BeginSend()/EndSend和BeginReceive()/EndReceive()两组方法与客户端进行收发通信
返回,再次等待新的连接请求
关闭套接字
代码示例
[csharp] viewplain copy
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace AsyncServer
{
public class AsyncTCPServer
{
public void Start()
{
//创建套接字
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6065);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定端口和IP
socket.Bind(ipe);
//设置监听
socket.Listen(10);
//连接客户端
AsyncAccept(socket);
}
/// <summary>
/// 连接到客户端
/// </summary>
/// <param name="socket"></param>
private void AsyncAccept(Socket socket)
{
socket.BeginAccept(asyncResult =>
{
//获取客户端套接字
Socket client = socket.EndAccept(asyncResult);
Console.WriteLine(string.Format("客户端{0}请求连接...", client.RemoteEndPoint));
AsyncSend(client, "服务器收到连接请求");
AsyncSend(client, string.Format("欢迎你{0}",client.RemoteEndPoint)); <
24613
/span>
AsyncReveive(client);
}, null);
}
/// <summary>
/// 接收消息
/// </summary>
/// <param name="client"></param>
private void AsyncReveive(Socket socket)
{
byte[] data = new byte[1024];
try
{
//开始接收消息
socket.BeginReceive(data, 0, data.Length, SocketFlags.None,
asyncResult =>
{
int length = socket.EndReceive(asyncResult);
Console.WriteLine(string.Format("客户端发送消息:{0}", Encoding.UTF8.GetString(data)));
}, null);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="client"></param>
/// <param name="p"></param>
private void AsyncSend(Socket client, string p)
{
if (client == null || p == string.Empty) return;
//数据转码
byte[] data = new byte[1024];
data = Encoding.UTF8.GetBytes(p);
try
{
//开始发送消息
client.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
{
//完成消息发送
int length = client.EndSend(asyncResult);
//输出消息
Console.WriteLine(string.Format("服务器发出消息:{0}", p));
}, null);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
客户端
基本流程
创建套接字并保证与服务器的端口一致使用BeginConnect()和EndConnect()这组方法向服务端发送连接请求
使用BeginSend()/EndSend和BeginReceive()/EndReceive()两组方法与服务端进行收发通信
关闭套接字
代码示例
plain copy
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace AsyncClient
{
public class AsyncTCPClient
{
/// <summary>
/// 连接到服务器
/// </summary>
public void AsynConnect()
{
//端口及IP
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6065);
//创建套接字
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//开始连接到服务器
client.BeginConnect(ipe, asyncResult =>
{
client.EndConnect(asyncResult);
//向服务器发送消息
AsynSend(client,"你好我是客户端");
AsynSend(client, "第一条消息");
AsynSend(client, "第二条消息");
//接受消息
AsynRecive(client);
}, null);
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="socket"></param>
/// <param name="message"></param>
public void AsynSend(Socket socket, string message)
{
if (socket == null || message == string.Empty) return;
//编码
byte[] data = Encoding.UTF8.GetBytes(message);
try
{
socket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
{
//完成发送消息
int length = socket.EndSend(asyncResult);
Console.WriteLine(string.Format("客户端发送消息:{0}", message));
}, null);
}
catch (Exception ex)
{
Console.WriteLine("异常信息:{0}", ex.Message);
}
}
/// <summary>
/// 接收消息
/// </summary>
/// <param name="socket"></param>
public void AsynRecive(Socket socket)
{
byte[] data = new byte[1024];
try
{
//开始接收数据
socket.BeginReceive(data, 0, data.Length, SocketFlags.None,
asyncResult =>
{
int length = socket.EndReceive(asyncResult);
Console.WriteLine(string.Format("收到服务器消息:{0}", Encoding.UTF8.GetString(data)));
AsynRecive(socket);
}, null);
}
catch (Exception ex)
{
Console.WriteLine("异常信息:", ex.Message);
}
}
}
}
从总体上来讲Socket异步编程的逻辑性更加明确了,因为我们只需要为每一个过程写好回调函数就好了。那么这个示例的效果如何呢?我们来看看它的演示效果:
总结
[csharp] view
plain copy
m_Socket.BeginConnect(this.m_ipEndPoint,
new AsyncCallback(this.ConnectCallBack),
this.m_Socket);//其中ConnectCallBack是一个回调函数
[csharp] view
plain copy
或者
[csharp] view
plain copy
m_Socket.BeginConnect(this.m_ipEndPoint,asyncResult=>
{
//在这里添加更多代码
},null)
博主为什么要在这里说这两种写法呢,有两个原因:
* 第二种写法更为简洁,无需去构造容器传递Socket和消息,因为它们都是局部变量。如果我们使用第一种方法,因为主函数和回调函数是两个不同的函数,因此如果想要共享变量就需要通过IAsyncResult接口来访问容器中的值,这样显然增加了我们的工作量。
* 第二种写法更为优雅,这似乎是C#语言中某种高级语法,具体叫什么我忘了,反正在Linq中经常看到这种写法的影子。
综合以上两个观点,博主还是建议大家使用第二种写法,博主打算有空的话将之前写的程序再重新写一遍,看看能不能找出代码中的问题。好了,今天的内容就是这样了,谢谢大家,希望大家喜欢!
相关文章推荐
- C#中Socket通信编程的异步实现
- C#中Socket通信编程的异步实现
- 异步Socket通信编程的C#实现(1)
- C#中Socket通信编程的异步实现
- C#中Socket通信编程的异步实现
- 异步Socket通信编程的C#实现(2)
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分(转)
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分(来源:http://blog.csdn.net/yangjundeng/archive/2005/03/17/321920.aspx)
- DirectX编程:C#中利用Socket实现网络语音通信[初级版本]
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(二)----使用方法
- C#中使用异步Socket编程实现TCP网络服务的CS的通讯构架(一)----基础类库部分
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分
- 基于C#的socket编程的TCP异步实现
- 在C#中使用异步Socket编程实现TCP网络服务
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(二)----使用方法
- 基于C#的socket编程的TCP异步实现
- 基于C#的socket编程的TCP异步实现
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分