关于socket异步通信的一些疑惑

lhonyun_lhy 2012-04-08 04:59:56

private Socket socket = null;
public void Listener()
{
if (listenState == true)
{
IPAddress ipe = IPAddress.Parse(f1.concls.ipe.Trim());
IPEndPoint ipEndPoint = new IPEndPoint(ipe, f1.concls.port);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ipEndPoint);
socket.Listen(50);
socket.BeginAccept(new AsyncCallback(EndAcceptSocket), socket);
}
else
{
socket.Close();
return;
}
}
public void EndAcceptSocket(IAsyncResult iasy)
{
if (listenState == true)
{
try
{
Socket client = socket.EndAccept(iasy);//连接建立之后将通道赋值给client
SocketCls socketcls;
socketcls = new SocketCls();
socketcls.socket = client;
client.BeginReceive(socketcls._buffer, 0, socketcls.buffersize, 0, new AsyncCallback(EndReceiveSocket), socketcls);
socket.BeginAccept(new AsyncCallback(EndAcceptSocket), socket);
}
catch (Exception e)
{

}
}
else
{
return;
}
}
public void EndReceiveSocket(IAsyncResult iasy)
{
SocketCls socketcls = (SocketCls)iasy.AsyncState;
Socket client = socketcls.socket;
int len = client.EndReceive(iasy);
byte[] buffer = new byte[len];
buffer = socketcls._buffer;
f1.AddText(len.ToString());
client.BeginReceive(socketcls._buffer, 0, socketcls.buffersize, 0, new AsyncCallback(EndReceiveSocket), socketcls);
}

第一点,新连接过来之后socket.BeginAccept(new AsyncCallback(EndAcceptSocket), socket);这里是不是开启了一个新的线程?public void EndAcceptSocket(IAsyncResult iasy)这个方法与Listener()是不是已经不是同一个线程了?
第二点,监听是个无限循环,那么新连接过来之后在哪里捕获这个链接然后执行BeginAccept的,是Listener()这个方法还是EndAcceptSocket(IAsyncResult iasy)这个方法。我理解的是Listener()只执行一次,之后便在EndAcceptSocket(IAsyncResult iasy)这里无限循环不知道对不对。
第三点,链接建立之后发送数据是直接从public void EndReceiveSocket(IAsyncResult iasy)这个方法开始的吗?
第四点,求大哥大姐们帮小弟理清socket异步通信的执行次序,我现在越想越迷糊,再次拜谢,不胜感激!
...全文
307 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
lhonyun_lhy 2012-04-09
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

你想“理清socket异步通信的执行次序”,那么首先放弃同步、顺序、函数式的思维方式,想象一下并发多线程吧。异步回调可能随时被执行,这无法用一个平面图来简单描述出来“次序”的。
[/Quote]
万分感谢!
zhangjie_it 2012-04-09
  • 打赏
  • 举报
回复
begin***就是瞬时返回,然后另外单独的线程处理;主线程往下进行。
zhangjie_it 2012-04-09
  • 打赏
  • 举报
回复
我最近也在研究socket,也是得到多次sp1234大神的指点;膜拜啊!

楼主的1,2,3,4点的理解和我的理解一体一致!
  • 打赏
  • 举报
回复
你想“理清socket异步通信的执行次序”,那么首先放弃同步、顺序、函数式的思维方式,想象一下并发多线程吧。异步回调可能随时被执行,这无法用一个平面图来简单描述出来“次序”的。
zuowen8605 2012-04-08
  • 打赏
  • 举报
回复
之前在论坛里好像看过一个类似的问题,我对这块的理解是这样的:
程序在进入回调之后,就会一直循环的调用socket.BeginAccept(new AsyncCallback(EndAcceptSocket), socket);来创建新socket,
这句client.BeginReceive(socketcls._buffer, 0, socketcls.buffersize, 0, new AsyncCallback(EndReceiveSocket), socketcls);只是注册回调,EndReceiveSocket才是执行这个线程,即读取socket数据

[Quote=引用 8 楼 的回复:]

我理解的是这样不知道对不对,socket一直在监听,只要 socket.BeginAccept(new AsyncCallback(EndAcceptSocket), socket);这句一直在循环,不管是在Listener()中用while(true)还是在EndAcceptSocket()中调用它自身,只要有新的连接过来被socket.Listen(5)捕获到了就能建立新的通道。
每一个新……
[/Quote]
  • 打赏
  • 举报
回复
面向未来的编程(实际上现在已经有很多传统的系统开始想并行化编程方式进行移植了),应该非常熟悉异步回调的思想。不要用函数式思维来设计并行程序,如果用异步编程语法来套用顺序式编程的逻辑设计会非常纠结,而且你写出来的代码的代码量要比异步的代码大多了。
  • 打赏
  • 举报
回复
你说“监听”这个对、也不对。因为底层可以是中断、事件去驱动的监听机制,而不是什么循环监听。

那么,你的高层次的程序去搞个循环来等待着底层的中断事件,是得不偿失。所以应该是异步回调机制的编程思想。
lhonyun_lhy 2012-04-08
  • 打赏
  • 举报
回复
我理解的是这样不知道对不对,socket一直在监听,只要 socket.BeginAccept(new AsyncCallback(EndAcceptSocket), socket);这句一直在循环,不管是在Listener()中用while(true)还是在EndAcceptSocket()中调用它自身,只要有新的连接过来被socket.Listen(5)捕获到了就能建立新的通道。
每一个新连接过来之后都会new一个含有Socket的容器SocketCls,有多少个连接存在那么就有多少个client.BeginReceive(socketcls._buffer, 0, socketcls.buffersize, 0, new AsyncCallback(EndReceiveSocket), socketcls);在无限循环。对方用已经建立的通道发送消息的时候就去找与通道的Socket相同的socketcls来接收消息。请指正!
  • 打赏
  • 举报
回复
关于3和4你自己想一想吧。关键地是,没有使用什么循环来阻塞线程,而是注册一个回调就立刻“完成”了,从而往往用15个线程或许就能服务500个客户端与服务器交互通讯。
  • 打赏
  • 举报
回复
没有仔细看你的代码,大致花几秒时间理解了一下。你的问题:

1. 异步操作中BeginXXXX都是注册一个回调,而回调被执行时才是在系统线程池上的线程执行。至于说这个线程是不是当前线程,或者是另外其它线程,那是.net系统决定的。回调时的线程跟执行BeginXXX的,很有可能是不同的线程。

2. client.BeginReceive注册一个异步Receive,然后socket.BeginAccep立刻就注册一个异步Accept。这只是一种注册行为的重复出现,你要说它是循环也可以,但是它跟同步程序中的阻塞循环是不同的。

lhonyun_lhy 2012-04-08
  • 打赏
  • 举报
回复
自己顶,求高手!!!!!跪求!跪拜!泪眼朦胧了……
lhonyun_lhy 2012-04-08
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

如果你觉得异步通信不好掌握,可以用线程来处理比较直观(实际上Listener用循环是个很好的选择)。
当一个连接进来后,再用异步或者线程来进行通讯:
C# code

TcpListener listener = new TcpListener(...);
void StartListener()
{
ThreadPool.QueueUserWorkItem(state =>
……
[/Quote]
谢谢,但我还是想弄明白上面的问题,能帮忙分析下嘛?
zhangfortune 2012-04-08
  • 打赏
  • 举报
回复
刚刚看Socket,有点迷糊
gomoku 2012-04-08
  • 打赏
  • 举报
回复
如果你觉得异步通信不好掌握,可以用线程来处理比较直观(实际上Listener用循环是个很好的选择)。
当一个连接进来后,再用异步或者线程来进行通讯:

TcpListener listener = new TcpListener(...);
void StartListener()
{
ThreadPool.QueueUserWorkItem(state =>
{
try
{
listener.Start(50);
while (true)
{
Socket socket = listener.AcceptSocket(); //<--
StartTalking(socket); //<--
}
}
catch (SocketException se)
{
if (se.SocketErrorCode != SocketError.Interrupted) throw;
}
});
}
void StopListener()
{
listener.Stop();
}
comcyd 2012-04-08
  • 打赏
  • 举报
回复
帮顶,最近也在做socket

111,126

社区成员

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

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

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