IOCP

Destekleyen

 

TsgcWebSocketServer

TsgcWebSocketHTTPServer

 

*Özel Indy sürümü gerektirir.

 

Windows için IOCP, Indy'nin varsayılan olarak yaptığı gibi bağlantı başına bir iş parçacığı kullanmak yerine sınırlı bir iş parçacığı havuzu kullanarak binlerce bağlantıyı işlemeye olanak tanıyan bir API'dir.

Indy Sunucuları için IOCP'yi etkinleştirmek üzere IOHandlerOptions özelliğine gidin ve IOHandler Türü olarak iohIOCP seçin.


Server.IOHandlerOptions.IOHandlerType := iohIOCP;
Server.IOHandlerOptions.IOCP.IOCPThreads := 0;
Server.IOHandlerOptions.IOCP.WorkOpThreads := 0;
Server.IOHandlerOptions.IOCP.PartialRequestTimeout := 0;
Server.IOHandlerOptions.IOCP.TCPKeepAlive.Enabled := True;
Server.IOHandlerOptions.KeepAliveTimeout := 120;

 

IOCPThreads, IOCP eşzamansız istekleri (örtüşen işlemler) için kullanılan iş parçacıklarıdır, varsayılan olarak değer sıfırdır; bu, iş parçacığı sayısının işlemci sayısı kullanılarak hesaplandığı anlamına gelir (cpucount işlevinin desteklenmediği Delphi 7 ve 2007 hariç; bu durumda iş parçacığı sayısı 32 olarak ayarlanır).

WorkOpThreads, istekleri işlemek üzere hazır tutulan en az iş parçacığı sayısını belirler; varsayılan değer 0'dır. Bir IOCP iş parçacığı yalnızca tamamlanmış bir işlemi alır ve işi bu havuza devreder, böylece yavaş bir istemci yüzünden hiçbir zaman engellenmez. Tüm iş parçacıkları zaten meşgulken havuz talep üzerine sabit bir maksimuma kadar büyür, bu nedenle boyutunun önceden belirlenmesi gerekmez. Bu değeri yalnızca havuzun ilk istekten önce hazır olmasını istiyorsanız artırın; böylece başlangıçtaki bağlantı yoğunluğu sırasında iş parçacığı oluşturma maliyetinden kaçınmış olursunuz.

2026.9.0 sürümünde değişti. WorkOpThreads eskiden her bağlantıyı bu iş parçacıklarından birine sabitliyordu; böylece bir bağlantıdaki tüm istekler aynı iş parçacığında çalışıyor ve WorkOpRoundRobin, yeni bağlantıların bu iş parçacıkları arasında nasıl dağıtılacağını belirliyordu. Sabitleme kaldırıldı: bir isteğin geri kalanını bekleyen bir bağlantı, aynı iş parçacığına atanmış diğer tüm bağlantıları engelliyor ve sunucuyu durduruyordu. Artık aynı bağlantıdaki istekler farklı iş parçacıklarında çalışabilir; bu nedenle veritabanı bağlantısı veya iş parçacığına özel önbellek gibi iş parçacığı başına tutulan hiçbir şeyin bir bağlantıyı izlediği varsayılmamalıdır. WorkOpRoundRobin artık mevcut değildir. Bu özelliği kodunuzdan kaldırın ve Object Inspector içinde etkinleştirdiyseniz, formun .dfm dosyasındaki WorkOpRoundRobin satırını da silin; aksi halde form yüklenmez.

PartialRequestTimeout, sunucunun, uzunluğunu zaten bildiği bir HTTP istek gövdesinin geri kalanını beklemesine olanak tanır; milisaniye cinsindedir ve varsayılan olarak 0'dır, bu da onu devre dışı bırakır. Bu olmadan, örneğin birkaç pakette gönderilen büyük bir POST gibi, tek bir tamamlanma içinde tamamen ulaşmayan bir istek gövdesi sessizce atılır ve bağlantı yanıt verilmeden kapatılır. Bu bekleme, çok sayıda bağlantıya hizmet veren ve asla engellenmemesi gereken bir IOCP iş parçacığında hiçbir zaman çalışmaz; bunun yerine, yukarıda açıklanan ve talep üzerine sabit bir maksimuma kadar büyüyen iş parçacığı havuzunda çalışır, böylece yavaş veya yanıt vermeyen bir istemci bu havuzu tüketip diğer bağlantıları geride bırakamaz.

TCPKeepAlive, işletim sisteminin boşta kalan bağlantıları yoklamasına ve sessizce kaybolmuş bir eşi (peer) algılamasına olanak tanır (varsayılan olarak devre dışıdır). TCPKeepAlive.Enabled True olarak ayarlandığında, işletim sistemi bir bağlantı TCPKeepAlive.Time saniye (varsayılan olarak 60) boyunca boşta kaldıktan sonra bu bağlantıyı yoklamaya başlar ve eş yanıt verene veya bağlantı kesilene kadar her TCPKeepAlive.Interval saniyede (varsayılan olarak 10) bir bu işlemi tekrarlar.

KeepAliveTimeout, belirtilen saniye sayısından daha uzun süre boşta kalan bağlantıları kapatır (varsayılan olarak 0, yani devre dışı anlamına gelir). Yalnızca boşta olan bağlantılar bu durumdan etkilenir; okunmakta olan bir istek veya yazılmakta olan bir yanıt bu zaman aşımı tarafından asla kesintiye uğratılmaz. Bu, varsayılan bağlantı başına iş parçacığı (thread-per-connection) IOHandler'ının sessiz bir bağlantıyı serbest bırakma şekline en yakın eşleşmedir ve işletim sistemine ya da eşin herhangi bir işbirliğine bağlı değildir.

 

Windows sunucuları için IOCP'yi etkinleştirmek, binlerce bağlantıyı işlemeniz gerektiğinde önerilir. Sunucunuz yalnızca en fazla 100 eşzamanlı bağlantıyı işliyorsa, varsayılan Indy iş parçacığı modeliyle kalabilirsiniz.

 

 

OnDisconnect olayı tetiklenmiyor

 

IOCP, varsayılan indy IOHandler'dan farklı çalışır. Varsayılan Indy IOHandler ile her bağlantı bir iş parçacığında çalışır ve bu iş parçacıkları her zaman çalışır, bağlantının etkin olup olmadığını kontrol eder, böylece bir bağlantı kesilmesi olursa kısa bir süre içinde bildirilir.

 

IOCP farklı çalışır, indy'nin varsayılan olarak yaptığı gibi 1 iş parçacığı = 1 bağlantı yerine, tüm bağlantıları işleyen bir iş parçacığı havuzu vardır. IOCP için, bir bağlantının hâlâ canlı olup olmadığını algılamanın tek yolu sokete yazmayı denemektir. Herhangi bir hata varsa, bu bağlantının kapalı olduğu anlamına gelir. Bağlantı kesilmelerini algılamak için 3 seçenek vardır:

 

1. TsgcWebSocketClient kullanıyorsanız, bunu Options özelliğinde etkinleştirebilirsiniz, CleanDisconnect := True (varsayılan olarak devre dışıdır). Etkinleştirilirse, istemci bağlantıyı kesmeden önce sunucuya bağlantı kesilmesi hakkında bilgilendiren bir mesaj gönderir, böylece sunucu bu mesajı alır ve OnDisconnect olayı tetiklenir.

2. sunucu tarafında heartbeat etkinleştirebilirsiniz, örneğin her 60 saniyede bir, böylece bağlı tüm istemcilere bir ping göndermeye çalışır ve bağlantısı kesilen bir istemci varsa OnDisconnect çağrılır.

3. Sunucunun IOHandlerOptions özelliğinde TCPKeepAlive'ı etkinleştirebilir ve/veya KeepAliveTimeout'u ayarlayabilirsiniz. Bunlar, örneğin istemci çöktüğü veya ağ bağlantısı bir kapatma mesajı gönderilmeden koptuğu için sessizleşen bir eşi, istemcinin herhangi bir şey göndermesine bağlı kalmadan sunucunun kendisinin algılayıp bağlantıyı kapatmasını sağlar.