首页 新闻 会员 周边

C# socket send/sendAsync 确定是否发送到对方

0
[已关闭问题] 关闭于 2015-04-02 08:56

在MSDN上的解释

send

If you are using a connection-oriented protocol, Send will block until all of the bytes in the buffer are sent, unless a time-out was set by using Socket.SendTimeout. If the time-out value was exceeded, the Send call will throw a SocketException. In nonblocking mode, Send may complete successfully even if it sends less than the number of bytes in the buffer. It is your application's responsibility to keep track of the number of bytes sent and to retry the operation until the application sends the bytes in the buffer. There is also no guarantee that the data you send will appear on the network immediately. To increase network efficiency, the underlying system may delay transmission until a significant amount of outgoing data is collected. A successful completion of the Send method means that the underlying system has had room to buffer your data for a network send.

https://msdn.microsoft.com/zh-cn/library/w93yy28a%28v=vs.110%29.aspx

sendAsync

For message-oriented sockets, do not exceed the maximum message size of the underlying Windows sockets service provider. If the data is too long to pass atomically through the underlying service provider, no data is transmitted and the SendAsync method throws a SocketException with the SocketAsyncEventArgs.SocketError set to the native Winsock WSAEMSGSIZE error code (10040).

Note that the successful completion of the SendAsync method does not indicate that the data was successfully delivered.

https://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.sendasync%28v=vs.110%29.aspx

在C# socket下什么是阻塞和不阻塞?难道同步的方法就是阻塞式的,异步方法(begin,async)是非阻塞的?

还有就是,如果上面成立,阻塞式就是等到数据发送到对方才返回,非阻塞式就是拷贝到系统缓存区返回?

CX_的主页 CX_ | 初学一级 | 园豆:75
提问于:2015-03-20 09:45
< >
分享
所有回答(1)
0

我觉C#得异步也是阻塞的,在EndRecieve时阻塞,只是这个EndRecieve阻塞在IO线程池中。

不过在C++中基于完成端口的异步是在Begin后把套接字句柄交给内核,内核接收到通知(如缓冲区发送完成,接收完成)之后唤醒挂起线程。(其实C#的异步也是同样的原理,只是被.NET包装了而已)

大芝麻 | 园豆:4 (初学一级) | 2015-03-20 09:53

刚刚查了下资料,在每个socket里是有blocking属性的,每个新建的socket默认blocking是true的,

MSDN;

If you are in blocking mode, and you make a method call which does not complete immediately, your application will block execution until the requested operation completes. If you want execution to continue even though the requested operation is not complete, change the Blocking property to false. The Blocking property has no effect on asynchronous methods. If you are sending and receiving data asynchronously and want to block execution, use the ManualResetEvent class.

https://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.blocking%28v=vs.110%29.aspx

所以不知道这么理解是不是对的,对于同步方法,默认是阻塞的,同时你也可以设置为非阻塞,但是对于非阻塞,系统不保证,数据立刻发送出去,阻塞式会一直阻塞,知道发送成功或者是超时。

但是对于一部方法,blocking是没用的,因为异步的方法,只是将数据拷贝到系统缓冲区。

不知道以上是否理解有误

支持(0) 反对(0) CX_ | 园豆:75 (初学一级) | 2015-03-20 10:24

@CX_: 这样理解应该是没问题的,但是同步方法设置为非阻塞,那么数据是否发送完成,你并不知道。

异步的话会收到通知

支持(0) 反对(0) 大芝麻 | 园豆:4 (初学一级) | 2015-03-20 10:32

@大芝麻: 所以,觉得还不是很懂,还要从下往上去研究,有很多东西要学,

不过谢谢你的回复

支持(0) 反对(0) CX_ | 园豆:75 (初学一级) | 2015-03-20 10:35

@CX_: 我说的不一定对,不过建议你多去试试C#的异步通信,如果有时间再看看C++的IO完成端口模型。应该就会没问题了

支持(0) 反对(0) 大芝麻 | 园豆:4 (初学一级) | 2015-03-20 10:40

@大芝麻: 我现在就是在看C# 异步通信,我不确定,异步的send(sendAsync)返回成功是代表发送到对方了,还是成功拷贝到系统缓冲区了,或者说在什么模式下的send是发送到对方返回,什么模式下拷贝到系统缓冲区返回

支持(0) 反对(0) CX_ | 园豆:75 (初学一级) | 2015-03-20 10:44

@CX_: 这个自己写个客户端调试接收前后服务端的情况就知道了嘛

支持(0) 反对(0) 大芝麻 | 园豆:4 (初学一级) | 2015-03-20 10:49

@CX_: 没必要纠结着两个问题,流程都是先往缓冲区写数据,至于什么时候发送,和设置缓冲区大小以及当前缓冲区数据量有关。send(sendAsync)只是.net一种编程模型而已,sendAsync是一种send的变异,sendAsync相当于调用send后就不管了,当事情做完后,一个句柄会回调给委托方法。sendAsync 返回成功不足以用来判断发送给了对方到了对方,注意这个到,及时是send返回成功也不意味着一定到。

另外说道阻塞和不阻塞,不管是socket,还是winsocket,表示的意义都不是send(sendAsync)所能表示的。那是在创建socket时,由参数指定的。哥们看得什么书,要么书不行,要么看书不仔细。

支持(0) 反对(0) arg | 园豆:1047 (小虾三级) | 2015-03-20 16:57

@大芝麻: 已经测试

支持(0) 反对(0) CX_ | 园豆:75 (初学一级) | 2015-03-26 17:58
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册