beginSend和beginReceive

深入理解BeginSend与Socket
本文探讨了.netsocket的BeginSend和BeginReceive方法如何利用完成端口提高网络编程效率。对比了BeginSend与Send方法在网络延迟高时的表现,并讨论了BeginReceive在减少线程阻塞方面的优势。

经过一番研究,终于可以确认,.net socket的beginSend和beginReceive用的是完成端口。(windows 98上不是,因为98没有这样的机制)。如果微软没有撒谎的话。
发送大量数据时,Socket.BeginSend和Socket.Send的速度是有差别的。在局域网里面,这种差别表现不明显。
但是在一个高延迟的网络中,差别就很大。
Socket.Send方法是可靠的。但是Send的时候,是等到缓冲区发出的包被确认以后才继续发送后续的包。所以,即使网络的带宽很大,但是如果网络延迟高,发送速度也会很慢。
Socket.BeginSend(异步)是把要发送的数据直接写入缓冲区,然后调用返回。BeginSend发送的时候,并不能确定发送是否成功。BeginSend的时候,指定了一个回调方法,发送成功后,系统会调用这个回调方法。在回调方法中,可以通过EndSend来检查实际发送的字节数。
虽然msdn中没有说明,但是实际上在EndSend中返回的字节数总是等于发送的字节数,或者抛出异常。
BeginSend的发送速度,可以占用全部的网络带宽。而Send的速度受网络延时的影响很大。在网络延迟高的网络中,可能每秒只有几K的速度。实际上,这个速度大致等于系统发送时的每个ip包的大小除以网络延迟的秒数。
完成端口使用的要点,就是减少系统中线程的数量。
所以,不要以为用了BeginSend就一定可以提高系统的负载能力。主要还是在于减少系统中工作的线程数量。所以,尽量不要在线程中使用阻塞的方法。

Socket.BeginReceive方法和Socket.Receive方法,对接受的速度没有影响。因为根据tcp协议,既然这个包已经到了应用 层,那么肯定是已经实际收到了。用BeginReceive的优势是在于可以不阻塞线程,从而减少系统中工作的线程。对于负载量不大的系统,用 Receive就可以了。Receive的逻辑比较简单。但是需要记住一点,Receive时返回的字节数,不一定等于要求读取的字节数。系统只是在数据 包到达时,尽可能的读取要求的字节数。

.net的Socket Api其实是对系统Socket Api的封装。所以以上的说法同样适用于winsock。但是由于BeginSend方法封装了完成端口,所以可以在获得高性能的同时,少了很多麻烦。对于网络的编程,是非常美妙的一件事情。

BeginSend需要注意的是,一定要控制发送的速度。否则,这个连接一定会因为系统缓冲区满而抛出异常。控制速度的办法就是在发送时计算发送的包数 量,在EndSend的时候计算发送成功的包数量。在发送之前,检查未发送的包数量,如果小于预设值则发送,否则暂停。这个地方会阻塞线程,所以也不是最 好的方法,比较好的办法,是自己做个发送缓冲队列。然后用一个专门的线程来处理发送。这样,只要用很少的线程,就可以处理发送。虽然BeginSend用 了完成端口,但是如果在系统中有大量被阻塞的线程,那就违背了完成端口的本意。

<think>好的,用户的问题是关于如何使用C#客户端API进行消息的发送接收操作,特别是基于控制台应用的Socket实现升级版。我需要先回顾一下之前的版本,然后看看如何升级。 首先,根据用户提供的引用[1],之前的客户端版本可能已经实现了基本的Socket连接消息发送功能。现在用户希望了解如何进一步升级,包括发送接收的完整流程,可能需要处理异步操作、错误处理以及如何同时进行发送接收。 接下来,我需要整理C#中Socket编程的基本步骤。客户端通常需要创建Socket对象,连接到服务器,然后使用SendReceive方法进行通信。但同步方法可能会导致阻塞,所以可能需要引入异步处理,比如使用BeginSendBeginReceive,或者使用async/await模式。 然后,考虑代码结构。用户提供的示例是Python的快速排序,但用户需要的是C#的代码示例。需要确保代码符合C#语法,并且包含必要的异常处理,比如try-catch块,以增强稳定性。 另外,用户可能希望同时发送接收消息,而不会互相阻塞。这可能需要多线程或异步编程。在C#中,可以使用Task.Run来启动接收消息的循环,而主线程处理用户输入发送消息。 还需要处理缓冲区、编码转换(比如字符串到字节数组),以及关闭连接时的资源释放。确保Socket正确关闭,避免资源泄漏。 可能的问题点包括:如何处理接收数据的部分消息,如何检测连接断开,以及如何优雅地退出程序。此外,可能需要使用ManualResetEvent或类似的同步机制来协调不同线程的操作。 最后,生成相关问题时要围绕Socket编程的扩展,比如多线程处理、协议设计、异常处理等,帮助用户深入理解。</think>以下是使用C#客户端API实现Socket消息发送与接收的详细教程: ### 一、基础客户端实现 ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; class Client { static void Main() { // 创建Socket对象 Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 连接服务器 IPEndPoint serverEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888); clientSocket.Connect(serverEP); // 发送消息 string message = "Hello Server"; byte[] sendBuffer = Encoding.UTF8.GetBytes(message); clientSocket.Send(sendBuffer); // 接收响应 byte[] recvBuffer = new byte[1024]; int bytesReceived = clientSocket.Receive(recvBuffer); Console.WriteLine($"收到响应:{Encoding.UTF8.GetString(recvBuffer, 0, bytesReceived)}"); clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); } } ``` ### 二、升级版实现(异步通信) ```csharp using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; class AdvancedClient { static Socket clientSocket; static byte[] buffer = new byte[1024]; static void Main() => MainAsync().Wait(); static async Task MainAsync() { try { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); await clientSocket.ConnectAsync(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888)); Console.WriteLine("已连接服务器"); // 启动接收任务 _ = Task.Run(ReceiveMessages); // 发送消息循环 while (true) { string input = Console.ReadLine(); if (input == "exit") break; byte[] data = Encoding.UTF8.GetBytes(input); await clientSocket.SendAsync(new ArraySegment<byte>(data), SocketFlags.None); } } catch (Exception ex) { Console.WriteLine($"错误:{ex.Message}"); } finally { clientSocket?.Close(); } } static async Task ReceiveMessages() { try { while (true) { var result = await clientSocket.ReceiveAsync( new ArraySegment<byte>(buffer), SocketFlags.None); if (result == 0) break; // 连接关闭 string received = Encoding.UTF8.GetString(buffer, 0, result); Console.WriteLine($"[服务器] {received}"); } } catch { Console.WriteLine("连接已断开"); } } } ``` ### 关键功能解析: 1. **异步连接**:使用`ConnectAsync`实现非阻塞连接 2. **双工通信**:独立线程处理消息接收(第24行) 3. **异常处理**:try-catch块保证程序稳定性[^1] 4. **编码处理**:采用UTF-8编码处理字符串(第29行)
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值