[C#]Socket通信BeginReceive異步接收數據何時回調Callback


原文地址: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 方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM