C#Socket.Send():它是否发送了所有数据?

时间:2018-04-03 04:02:08

标签: c# .net sockets tcp

我正在读一本名为" C#Network Programming"理查德布鲁姆。以下摘录指出Send()方法无法保证发送传递给它的所有数据。

byte[] data = new byte[1024];
int sent = socket.Send(data);
     

根据这段代码,你可能会想到这个   整个1024字节的数据缓冲区被发送到远程设备......但是这个   可能是一个糟糕的假设。取决于内部TCP的大小   缓冲区和传输的数据量有可能不是   提供给Send()mehtod的所有数据实际上都已发送。

但是,当我查看Microsoft文档https://msdn.microsoft.com/en-us/library/w93yy28a(v=vs.110).aspx时,它说:

  

如果您使用的是面向连接的协议,Send将阻止直到   除非设置了超时,否则将发送缓冲区中的所有字节

那是哪个?这本书于2004年出版,从那以后它有变化吗?

我打算使用异步套接字,所以我的下一个问题是,BeginSend()会发送所有数据吗?

2 个答案:

答案 0 :(得分:1)

您所要做的就是阅读您引用的完全相同段落的其余部分。在同一句话中,你的引语甚至是例外。

  

如果使用面向连接的协议,Send将阻塞,直到发送缓冲区中的所有字节为止,除非使用Socket.SendTimeout设置超时。如果超出超时值,Send调用将抛出SocketException。 在非阻塞模式下,即使发送的数量少于缓冲区中的字节数,Send也可能成功完成。在应用程序发送缓冲区中的字节之前,应用程序负责跟踪发送的字节数并重试操作。

对于<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> <!-- Optional theme --> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap-theme.min.css"> <!-- Latest compiled and minified JavaScript --> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script> <script src="js/myExternalFile.js"></script> <link rel="stylesheet" type="text/css" href="css/stylesheet.css"> <link href="https://fonts.googleapis.com/css?family=Allerta" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Crimson+Text" rel="stylesheet"> <title> My Website Name</title> </head> <body> <ul class="nav"> <img src="logos/navbar-logo.png"> <li><a class="hover" href="#Contact">Contact</a></li> <li><a class="active" href="#Careers">Careers</a></li> <li><a class="active" href="#Services">Services</a></li> <li><a class="active" href="#Drivers">Drivers</a></li> </ul> <div id="mycarousel" class="carousel slide" data-ride="carousel"> <!-- Indicators --> <ol class="carousel-indicators"> <li data-target="#mycarousel" data-slide-to="0" class="active"></li> <li data-target="#mycarousel" data-slide-to="1"></li> <li data-target="#mycarousel" data-slide-to="2"></li> <li data-target="#mycarousel" data-slide-to="3"></li> <li data-target="#mycarousel" data-slide-to="4"></li> </ol> <!-- Wrapper for slides --> <div class="carousel-inner" role="listbox"> <div class="item"> <img src="https://unsplash.it/2000/1250?image=397" data-color="lightblue" alt="First Image"> <div class="carousel-caption"> <h3>First Image</h3> </div> </div> <div class="item"> <img src="https://unsplash.it/2000/1250?image=689" data-color="firebrick" alt="Second Image"> <div class="carousel-caption"> <h3>Second Image</h3> </div> </div> <div class="item"> <img src="https://unsplash.it/2000/1250?image=675" data-color="violet" alt="Third Image"> <div class="carousel-caption"> <h3>Third Image</h3> </div> </div> <div class="item"> <img src="https://unsplash.it/2000/1250?image=658" data-color="lightgreen" alt="Fourth Image"> <div class="carousel-caption"> <h3>Fourth Image</h3> </div> </div> <div class="item"> <img src="https://unsplash.it/2000/1250?image=638" data-color="tomato" alt="Fifth Image"> <div class="carousel-caption"> <h3>Fifth Image</h3> </div> </div> </div> <!-- Controls --> <a class="left carousel-control" href="#mycarousel" role="button" data-slide="prev"> <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span> <span class="sr-only">Previous</span> </a> <a class="right carousel-control" href="#mycarousel" role="button" data-slide="next"> <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span> <span class="sr-only">Next</span> </a> </div>,还描述了行为:

  

您的回调方法应该调用EndSend方法。当您的应用程序调用BeginSend时,系统将使用单独的线程来执行指定的回调方法,并且将在EndSend上阻塞,直到Socket发送所请求的字节数或引发异常

这不是一个非常好的设计,并且击败了回调的全部内容!请考虑使用SendAsync代替(然后您仍然需要检查BeginSend属性)。

答案 1 :(得分:0)

您引用的两个资源都是正确的。我认为措辞本来可以更好。 在文档中,MSDN也写了

  

也无法保证您发送的数据会显示在   网络立即。为了提高网络效率,潜在的   系统可能会延迟传输,直到大量传出   收集数据。

所以pre > code方法阻塞,直到底层系统有空间来缓冲网络发送的数据。

  

成功完成Send方法意味着底层   系统有空间缓冲您的数据以进行网络发送。