簡體   English   中英

確保排隊的消息以正確的順序發送

[英]Ensure queued messages are sent in correct order

我有一個客戶端-服務器體系結構,使用TCP進行通信。 客戶端以1msg / 70ms的速率向客戶端發送消息。 服務器必須模擬網絡延遲,因此在服務器接收方面,我執行以下操作:

//Event handler for new messages
private void DataReceived(object sender, DataReceivedEventArgs args)
{
    //Add raw data to a queue for processing at a later time
    TemporaryRawMessages.Enqueue(args.Bytes);
    args.Recycle();
}

//Function running on thread; processes newly arrived raw messages
//new messages are removed from the queue, given their own thread and processed independently. 
void ProcessMessagesIn()
{
    while (true)
    {

        if (TemporaryRawMessages.Count > 0)
        {
            var raw = TemporaryRawMessages.Dequeue();
            var t = new Thread(() => {
                Thread.Sleep(LatencyUp);
                var message = (ClientToServerMessage)Utils.Deserialize(raw_message);
                Messages_In.Enqueue(message);
            });
            t.Start();
        }

    }
}

//Create & start a thread to processes incoming messages
var processMessagesIn = new Thread(ProcessMessagesIn);
processMessagesIn.Start();

注意LatencyUp變量。 我希望來自客戶端的郵件延遲bx毫秒,但均勻間隔為1msg / 70ms。 換句話說,所有消息相隔LatencyUp ,但被LatencyUp抵消。

我還向從服務器發送到客戶端的消息添加了延遲,以表示網絡停機延遲:

Task.Factory.StartNew(() => { SendLoop(); });

void SendToClient(ServerToClientMessage message)
{
    Messages_Out.Enqueue(message);
}

void SendLoop()
{
    while (true)
    {
        if(Messages_Out.Count > 0)
        {
            ServerToClientMessage message_out = null;
            Messages_Out.TryDequeue(out message_out);

            if(message_out != null)
            {
                Thread myNewThread = new Thread(() =>
                {
                    Thread.Sleep(LatencyDown);
                    if (ClientConnection != null && ClientConnection.State == ConnectionState.Connected)
                    {
                        var serialized = Utils.Serialize(message);
                        ClientConnection.SendBytes(serialized, SendOption.Reliable);
                    }
                });

                myNewThread.Start();
            }
        }
    }
}

我也嘗試過這樣發送,而沒有從服務器到客戶端的消息隊列:

void SendToClient(ServerToClientMessage message)
{
    Thread myNewThread = new Thread(() =>
    {
        Thread.Sleep(LatencyDown);
        Send(message);
    });

    myNewThread.Start();
}

問題

有時,從服務器到客戶端的消息會混雜在一起,例如,消息2可能在消息1之前發送。

我不確定為什么。 郵件以正確的順序放入隊列(我已經檢查過了)。 在添加到隊列與出隊+發送之間的某個地方出了點問題。

我唯一能想到的是一個線程在另一個線程之前完成,但是我不認為這將如何發生。

如何確保消息按發送順序(從客戶端到服務器)接收並以正確的順序從服務器發送到客戶端?

性能(就處理速度而言)很重要,因此,也應贊賞有關該主題的任何改進/建議。

您不能使用多個線程按順序分派事件。 如果您想為數據生產者提供一個異步使用者,那么您只需要一個線程即可。

創建生產者-消費者隊列的最簡單方法是使用BlockingCollection<T>

var blockingCollection = new BlockingCollection<int>();

// this is a single, one and only producer thread
Task.Run(() =>
{
    var number = 0;
    while (true)
    {
        number++;
        Console.WriteLine("tx --> " + number);
        blockingCollection.Add(number);
        Task.Delay(1000).Wait();
    }
});

// single, one and only consumer thread
foreach (var item in blockingCollection.GetConsumingEnumerable())
{
    Task.Delay(200).Wait();
    Console.WriteLine("    " + item + " --> rx");
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM