socket通信中为什么要用到回调函数?

zteclx 2010-04-17 09:49:25
在SOCKET通信的服务器端,为什么一般要用到回调函数?使用线程可以理解,一般是为了系统不处于类似死机;那是用回调函数又是为什么呢?
...全文
818 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
leyt 2010-04-18
  • 打赏
  • 举报
回复
回调是实现异步操作比较好的方法之一
superzxf 2010-04-18
  • 打赏
  • 举报
回复
回调的过程其实就是调用方把函数指针传递给被调用方,对方在合适的时候通过这个函数指针调用所指的函数,由于实际的调用是对方发起的,故称为回调
.net中的委托其实就是一种回调,而委托最常用来表示事件,参考事件的触发过程就能理解回调
白头老汉 2010-04-18
  • 打赏
  • 举报
回复
也未必要用回调函数,不用也可以。
zteclx 2010-04-18
  • 打赏
  • 举报
回复
本人比较愚钝,回调E文应该是recallback,可以翻译为“重新回去调”,既然要回去调,作用是什么呢?为什么要“回去调”
zteclx 2010-04-18
  • 打赏
  • 举报
回复
回调的好处应该就是可以把方法当参数来使用
bluedoctor 2010-04-18
  • 打赏
  • 举报
回复
关注中。。。。。。。
zteclx 2010-04-18
  • 打赏
  • 举报
回复
http://www.programfan.com/club/showpost.asp?id=13615
zteclx 2010-04-18
  • 打赏
  • 举报
回复
搜到的一篇文章:
http://www.csharpwin.com/csharpspace/6115r972.shtml
C#异步通信概念及应用的认识首先让我们来看看:在网络编程中运用Socket,常常需要长期监听某个端口,以获得Socket连接,进而执行相关操作。

但此时,主线程就会被阻塞,无法做其他事情。为了解决这类问题,Socket类中提供了一些支持异步操作的方法,如表17-10所示。

下表为Socket类中支持异步操作的方法

方 法
说 明

BeginAccept()
开始一个异步请求,以创建一个新的Socket对象来接受传入的连接请求

EndAccept()
结束一个异步请求,以创建一个新的Socket对象来接受传入的连接请求

BeginConnect()
开始一个对远程主机的异步请求

EndConnect()
结束一个对远程主机的异步请求

BeginDisconnect()
开始异步请求从远程主机断开连接

EndDisconnect()
结束从远程主机断开连接的异步请求

BeginReceive()
开始从连接的Socket中异步接收数据

EndReceive()
结束从连接的Socket中异步接收数据

BeginReceiveFrom()
开始从指定网络设备中异步接收数据

EndReceiveFrom()
结束从指定网络设备中异步接收数据

BeginSend()
开始将数据异步发送到连接的Socket中

EndSend()
结束数据的异步发送

BeginSendFile()
开始将文件异步发送到连接的Socket中

EndSendFile()
结束文件的异步发送

BeginSendTo()
向特定的远程主机异步发送数据

EndSendTo()
结束对远程主机数据的异步发送



从上表中可以看出,这些方法都是成对出现的。这些方法能避免网络通信中的阻塞现象。这些方法的使用机制是在Begin开头的方法中注册一个回调函数,当对应的事件发生时,调用该回调函数,且在回调函数中调用对应的End开头的方法。

下面以BeginAccept()和EndAccept()为例,说明异步方法的用法。BeginAccept()的声明如下所示。

public IAsyncResult BeginAccept(AsynCallback callback, object state); 其中,第一个参数是异步委托AsynCallb了ack,state包含此请求的状态信息的对象。

EndAccept()方法具有三种重载形式,如下所示。

public Socket EndAccept(IAsyncResult asynresult); public Socket EndAccept(out byte[] buffer, IAsyncResult asynresult); public Socket EndAccept(out byte[] buffer, out int bytesTransferred, IAsyncResult asynresult,); asynresult用于存储此异步操作的状态信息及任何用户定义的数据;buffer表示需要传输的字节数据;

bytesTransferred表示已经传输的字节数。这里的out参数与ref的用法类似,均表示传递引用。它们的区别是ref是传递参数的地址,out是返回值。

具体用法如下所示。

private AsyncCallback callbackOnAccpt; //定制回调方法 private Socket s; …… //C#异步通信 s=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); callbackAccpt = new AsyncCallback(this.OnAccept);//实例化回调方法 s.BeginAccept(callbackOnAccpt, this.s); //开始异步请求 …… private void OnAccept(IAsyncResult asynresult) { //C#异步通信…… s.EndAccept(asynresult); //结束异步请求 …… } BeginConnect()和EndConnect()用于对远程主机的异步连接请求。BeginConnect()的声明如下所示。

public IAsyncResult BeginConnect(EndPoint remoteEP, AsyncCallback callback, object state); public IAsyncResult BeginConnect(IPAddress address, int port,AsyncCallback requestedcallback,object state); public IAsyncResult BeginConnect(IPAddress[] address, int port,AsyncCallback requestedcallback,object state); //C#异步通信public IAsyncResult BeginConnect(string host,int port, AsyncCallback requestedcallback,object state); 它的每个重载形式均含有AsyncCallback参数,这是这类Begin开头的方法的特点;remoteEP表示远程主机的IP和端口。

EndConnect()的声明如下所示。

public Socket EndConnect(IAsyncResult asynresult);

它的参数的意义和EndAccept()完全一致。

BeginSend()表示开始将数据异步发送到连接的Socket,它最常用的声明如下所示。

public IAsyncResult BeginSend(byte[] buffer, int offset,int size,SocketFlags socketFlags, AsyncCallback callback,object state); Buffer表示要发送的数据,offset表示buffer中发送数据的位置,size为发送字节数的大小,socketFlags指SocketFlags值的按位组合。

EndSend()的声明如下所示。

public Socket EndSend(IAsyncResult asynresult); BeginReceive()表示开始从连接的Socket中异步接收数据,它的常见声明如下所示。

public IAsyncResult BeginReceive(byte[] buffer, int offset,int size,SocketFlags socketFlags, AsyncCallback callback,object state); 它的参数和BeginSend()是完全一致的,这里不再赘述。

EndReceive()的声明如下所示。

public Socket EndReceive(IAsyncResult asynresult); C#异步通信之Socket中异步通信的实现要远比同步困难,这里不再举例。简单地说,在同步中,主线程如果调用一个方法,那么主线程必须等到方法线程执行完才能继续往下执行。因此,主线程和方法线程的执行是串行的。而在异步中,两者能同时执行,它们的执行是并行的。

yx长弓 2010-04-17
  • 打赏
  • 举报
回复
--------------------------------------------------
回复于:2010-04-17 22:54:11
在.net系统中,人家就封装了异步操作,.net系统本身管理线程调度,然后处理好一切需要的工作之后只把结果传递给你的代码。由于人家的异步就是回调方式来通知你的程序的,那么你如果要使用socket的异步操作方法,当然就要使用到回调了。

不是因为回调时髦所以使用回调。所以如果你不看底层一点的道理,我简直无法回答你为什么会用到回调的问题。其实答案可以很简单轻松:“接口就是按照回调来定义的的所以当然要回调”,但是我想你肯定不满意这样的答复。
--------------------------------------------------
学习
  • 打赏
  • 举报
回复
在.net系统中,人家就封装了异步操作,.net系统本身管理线程调度,然后处理好一切需要的工作之后只把结果传递给你的代码。由于人家的异步就是回调方式来通知你的程序的,那么你如果要使用socket的异步操作方法,当然就要使用到回调了。

不是因为回调时髦所以使用回调。所以如果你不看底层一点的道理,我简直无法回答你为什么会用到回调的问题。其实答案可以很简单轻松:“接口就是按照回调来定义的的所以当然要回调”,但是我想你肯定不满意这样的答复。
  • 打赏
  • 举报
回复
嗯,如果你不习惯lamda表达式,我给你写个更原始一点的写法:
using System;
using System.Threading;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var method = new Func<int, int, int>(Times);
Console.WriteLine("程序开始");
method.BeginInvoke(3, 5, PrintResult, method);
Console.WriteLine("请按任意键退出程序.......");
Console.ReadKey();
}

static int Times(int x, int y)
{
Thread.Sleep(5000);
return x * y;
}

static void PrintResult(IAsyncResult h)
{
var m = (Func<int, int, int>)h.AsyncState;
Console.WriteLine("结果是{0}。", m.EndInvoke(h));
}
}
}
  • 打赏
  • 举报
回复
关于回调,实际上我实在不想断言它有什么好处。写个demo你自己体会一下吧。
using System;
using System.Threading;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var method= new Func<int,int,int>(Times);
Console.WriteLine("程序开始");
method.BeginInvoke(3, 5, h =>
{
Console.WriteLine("结果是{0}。", method.EndInvoke(h));
}, null);
Console.WriteLine("请按任意键退出程序.......");
Console.ReadKey();
}

static int Times(int x, int y)
{
Thread.Sleep(5000);
return x * y;
}
}
}
Code従業員 2010-04-17
  • 打赏
  • 举报
回复
为了多次监听吧。。。
  • 打赏
  • 举报
回复
我通常都没有.net系统的架构设计者更懂线程,所以我通常不用线程,我只用.net系统给我实现的将简单的线程封装得更高级的异步操作。

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧