Socket通信BeginReceive异步接收数据何时回调Callback

本文通过实际测试案例,深入探讨了Socket异步通讯中BeginReceive的回调机制,并给出了不同数据长度下BeginReceive的回调情况。
部署运行你感兴趣的模型镜像

转载连接: http://www.cnblogs.com/wangtonghui/p/3277303.html


最近在做服务器压力测试程序。

接触了一段时间Socket异步通讯,发现自己对BeginReceive什么时候回调产生了错误的理解。之前我一直以为异步接收数据只有当Buffer被填满的时候才会回调。如果这样当服务端的Buffer大于客户端发送的数据时,客户端发送的数据就不会得到及时的处理(当Buffer填满时才处理)。这显然是不合情理的,于是我做了如下测试:

服务端代码:

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace SocketServer
{
    class Program
    {
        //服务端buffer为4字节
        static byte[] buffer = new byte[4];
        static void Main(string[] args)
        {
            Console.WriteLine("[Server]");
            try
            {
                Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketServer.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4444));
                socketServer.Listen(int.MaxValue);
                Console.WriteLine("服务端已启动,等待连接...");
                //接收连接
                Socket ts = socketServer.Accept();
                Console.WriteLine("客户端已连接");

                //开始异步接收
                ts.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), ts);
                Console.ReadKey();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        static void ReceiveCallback(IAsyncResult result)
        {
            Socket ts = (Socket)result.AsyncState;
            ts.EndReceive(result);
            result.AsyncWaitHandle.Close();
            Console.WriteLine("收到消息:{0}", Encoding.ASCII.GetString(buffer));

            //清空数据,重新开始异步接收
            buffer = new byte[buffer.Length];
            ts.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), ts);
        }
    }
}
复制代码
客户端代码:
复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace SocketClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("[Client]");
            try
            {
                Socket socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketClient.Connect(IPAddress.Parse("127.0.0.1"), 4444);
                Console.WriteLine("发送消息:");
                //获取发送内容
                string sendStr = Console.ReadLine();
                while (!(sendStr.ToLower() == "q"))
                {
                    Console.WriteLine("发送消息:");
                    //同步发送数据
                      socketClient.Send(Encoding.ASCII.GetBytes(sendStr));
                    sendStr = Console.ReadLine();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine("按任意键退出");
                Console.ReadKey();
            }
        }
    }
}
复制代码

可以看到服务端采用异步接收的方式,每次接收不超过4个字节。客户端不限制一次发送数据的字节数。(备注:1.先运行服务端后运行客户端 2.发送数据采用ASCII编码,每个字符占用1个字节 3.Socket.ReceiveBufferSize应当大于Buffer长度,否则会得到其他结果)

测试结果:

测试结果

1.发送数据长度与接收Buffer长度一致,接收到所有数据回调;

2.发送数据长度大于接收Buffer长度,Buffer填满时回调,数据接收完时回调;

3.发送数据长度小于接收Buffer长度,数据接收完时回调;

如果想要手动强制使BeginReceive回调,MSDN提供的方法是:

若要取消挂起的 BeginReceive,请调用 Close 方法。


您可能感兴趣的与本文相关的镜像

Wan2.2-T2V-A5B

Wan2.2-T2V-A5B

文生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

(注意使用前先将IP改为自己的IP或127.0.0.1) 本软件是使用套接字、ReceiveCallBack(IAsyncResult AR)函数为例的客服实例,修正了关闭客户端会导致异常的Bug;并且还是一个RichTextBox颜色使用的范例,不同的事件使用不同的颜色:如用户登录用红色、用户名用绿色、聊天内容用黑色^_^! 代码附赠全套注释,帮助初学者学习使用。 下面是核心代码 private void ReceiveCallBack(IAsyncResult AR) { try { DateTime dt = DateTime.Now; //如果服务器突然关闭后,客户端还坚持与之连接就会弹出异常; //检查是否套接字还连接上就可以避免这一问题。 if (!ClientSocket.Connected) { return; } //挂起AR,独占的使用AR来接收传过来的内容 int REnd = ClientSocket.EndReceive(AR); string StrOfREnd=Encoding.Unicode.GetString(MsgBuffer, 0, REnd); //截断的传输过来的字符串,"\n"前的是用户名 "\n"后的是聊天的内容 string UsersName = StrOfREnd.Substring(0, StrOfREnd.LastIndexOf("\n")); string Content = StrOfREnd.Substring(StrOfREnd.LastIndexOf("\n")+1); string Login=StrOfREnd.Substring(0,2); //MessageBox.Show("缓存中的内容:" + StrOfREnd + "\n" + "截断的用户名:" + UsersName + "\n" + "截断的内容:" + Content); if (Login != "登录") { //第一个字符不为“登陆” int oldlenth = tb_RecieveMsg.TextLength; this.tb_RecieveMsg.Select(oldlenth, 0); this.tb_RecieveMsg.SelectionColor = Color.Green; string str = Encoding.Unicode.GetString(MsgBuffer, 0, REnd); str = str.Substring(1, str.Length - 1); //用户使用绿色字体 this.tb_RecieveMsg.AppendText(" " + string.Format("{0:T}", dt) + " " + "用户:" + UsersName + "说:" + "\r\n"); this.tb_RecieveMsg.SelectionColor = Color.Black; this.tb_RecieveMsg.AppendText(" " + Content + "\r\n"); this.tb_RecieveMsg.AppendText("\r\n"); } else {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值