對於這個問題的目的,我做了一個超級簡單的例子:的TcpListener服務器循環空轉,直到有一個掛起的連接
using System;
using System.Net;
using System.Net.Sockets;
namespace Loop
{
class Program
{
public static void Main (string[] args)
{
TcpListener server = new TcpListener(IPAddress.Any, 1337);
server.Start();
Console.WriteLine("Starting listener on {0}:{1}", IPAddress.Any, 1337);
while (true)
{
if (server.Pending())
{
Console.WriteLine("Activity...");
Socket client = server.AcceptSocket();
IPEndPoint clientAddress = (IPEndPoint) client.RemoteEndPoint;
Console.WriteLine("Accepted client: {0}:{1}", clientAddress.Address, clientAddress.Port);
client.Close();
Console.WriteLine("Closed connection to: {0}:{1}", clientAddress.Address, clientAddress.Port);
}
else
{
// Currently takes 100% of my CPU (well, actually Core - 25%, but you get the idea).
// How do I idle (CPU @ 0%) the loop until pending connection?
}
}
}
}
}
註釋已經包含的問題,但是,是的,我怎麼閒着循環,直到有一個實際的掛起連接,以便我的CPU沒有融化?
當給定套接字上存在未決連接時,是否有方法僅在OS事件上偵聽和喚醒? (喜歡的東西libuv (node.js)做,這就是爲什麼我添加single-threaded)
我實際的實現意味着一個相當基本的反應堆事件循環,但是,是的,我不知道如何傾聽與C#OS事件(如果有任何可能性)。
我知道BeginAccept
和另一堆異步系列,但這些人由於他們的多線程性質而不是可以接受的。
此外,我知道我可以簡單地在循環內Thread.Sleep
,但我正在尋找基於事件的行爲。
P.S.我正在使用Mono,目標是Linux可執行文件。
如果要使用阻塞樣式,可以先調用AcceptSocket而不等待第一個等待;該呼叫將阻止(不旋轉),直到連接被接受。或者,您可以在輪詢循環中添加一個Sleep來減少CPU開銷,但編寫網絡I/O代碼以避免輪詢並使用正確的同步工具僅在I/O可用時喚醒時會更好。 –
我只想指出'BeginAccept'不一定是多線程的(至少就你的代碼而言)。如果你提供了一個同步上下文,那麼如果你有權訪問'await' /'async','AcceptSocketAsync'非常容易使用,並且它將異步地處理事物,同時使用與同步非常相似的代碼,並完全解決多線程問題(因爲你實際上在你的代碼中一直在處理一個線程)。 Mono現在應該支持'await' /'async'。 – Luaan
@Luaan,多線程我認爲任何東西,每個請求產生額外的線程。 – jolt