के साथ प्रति सेकेंड प्राप्त करता है SocketAsyncEventArgs का उपयोग करके एक टीसीपी सर्वर विकसित किया जाता है और यह विंडोज सेवा के रूप में async विधियां है। मेरे पास मुख्य की शुरुआत में कोड की ये 2 पंक्ति है:20 सॉकेटएसिंसेन्ट आर्ट्स
ThreadPool.SetMaxThreads(15000, 30000);
ThreadPool.SetMinThreads(10000, 20000);
और दोनों सत्य वापस लौटे (लौटे गए मान लॉग हैं)। अब 2000 से 3000 क्लाइंट इस सर्वर पर संदेश भेजना शुरू कर देते हैं और यह कनेक्शन स्वीकार करना शुरू कर देता है (मैं कनेक्शन की संख्या गिनता हूं और यह अपेक्षित है - एक कनेक्शन पूल है)। सर्वर प्रक्रिया की थ्रेड गिनती ~ 2050 से ~ 3050 तक बढ़ेगी। अब तक सब ठीक है!
अब एक प्राप्त विधि है जिसे ReceiveAsync सत्य या SocketAsyncEventArgs की पूर्ण घटना के बाद या तो कॉल किया जाएगा।
और यहां समस्याएं शुरू होती हैं: इससे कोई फर्क नहीं पड़ता कि ग्राहक कितने संदेश जुड़े हैं और कितने संदेश भेजते हैं, प्राप्त किया जाएगा एक सेकंड में अधिकतम 20 बार कहा जाएगा! और जैसे-जैसे ग्राहकों की संख्या बढ़ जाती है, यह संख्या (20) ~ 10 तक गिर जाती है।
पर्यावरण: टीसीपी सर्वर और क्लाइंट एक ही मशीन पर अनुकरण किए जा रहे हैं। मैंने 2 मशीनों पर कोड का परीक्षण किया है, एक में 2-कोर सीपीयू और 4 जीबी रैम है और दूसरे में 8-कोर सीपीयू और 12 जीबी रैम है। कोई डेटा हानि नहीं है (अभी तक) और कभी-कभी मुझे प्रत्येक प्राप्त ऑपरेशन में 1 से अधिक संदेश प्राप्त होते हैं। कोई बात नहीं। लेकिन प्राप्त करने की संख्या कैसे बढ़ाया जा सकता है?
कार्यान्वयन पर अतिरिक्त नोट्स: कोड बड़ा है और इसमें कई अलग-अलग तर्क शामिल हैं। एक समग्र विवरण होगा: मेरे पास नए कनेक्शन स्वीकार करने के लिए एक एकल सॉकेटएसिंसेन्ट आर्ट्स है। यह बहुत अच्छा काम करता है। अब प्रत्येक नए स्वीकृत कनेक्शन के लिए मैं डेटा प्राप्त करने के लिए एक नया सॉकेटएसिंसेन्ट आर्ट्स बना देता हूं। मैंने पूल में यह एक (सॉकेटएसिंसेन्ट आर्ट्स प्राप्त करने के लिए बनाया) रखा है। इसका पुन: उपयोग नहीं किया जाएगा लेकिन कनेक्शन को ट्रैक करने के लिए उपयोगकर्ता टोकन का उपयोग किया जा रहा है; उदाहरण के लिए उन कनेक्शन जो डिस्कनेक्ट हैं या वे कनेक्शन जो 7 मिनट के लिए कोई डेटा नहीं भेजते हैं उन्हें बंद कर दिया जाएगा और डिस्प्ले किया जाएगा (सॉकेटएसिंसेन्ट एआरजीएस की स्वीकार्य सॉकेट बंद हो जाएगी (दोनों), बंद और डिस्पोजेड और इसी तरह सॉकेटएसिंक एवेन्ट ऑब्जेक्ट ऑब्जेक्ट होगा)।
class Sudo
{
Socket _listener;
int _port = 8797;
public Sudo()
{
var ipEndPoint = new IPEndPoint(IPAddress.Any, _port);
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind(ipEndPoint);
_listener.Listen(100);
Accept(null);
}
void Accept(SocketAsyncEventArgs acceptEventArg)
{
if (acceptEventArg == null)
{
acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += AcceptCompleted;
}
else acceptEventArg.AcceptSocket = null;
bool willRaiseEvent = _listener.AcceptAsync(acceptEventArg); ;
if (!willRaiseEvent) Accepted(acceptEventArg);
}
void AcceptCompleted(object sender, SocketAsyncEventArgs e)
{
Accepted(e);
}
void Accepted(SocketAsyncEventArgs e)
{
var acceptSocket = e.AcceptSocket;
var readEventArgs = CreateArg(acceptSocket);
var willRaiseEvent = acceptSocket.ReceiveAsync(readEventArgs);
Accept(e);
if (!willRaiseEvent) Received(readEventArgs);
}
SocketAsyncEventArgs CreateArg(Socket acceptSocket)
{
var arg = new SocketAsyncEventArgs();
arg.Completed += IOCompleted;
var buffer = new byte[64 * 1024];
arg.SetBuffer(buffer, 0, buffer.Length);
arg.AcceptSocket = acceptSocket;
arg.SocketFlags = SocketFlags.None;
return arg;
}
void IOCompleted(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
Received(e);
break;
default: break;
}
}
void Received(SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success || e.BytesTransferred == 0 || e.Buffer == null || e.Buffer.Length == 0)
{
// Kill(e);
return;
}
var bytesList = new List<byte>();
for (var i = 0; i < e.BytesTransferred; i++) bytesList.Add(e.Buffer[i]);
var bytes = bytesList.ToArray();
Process(bytes);
ReceiveRest(e);
Perf.IncOp();
}
void ReceiveRest(SocketAsyncEventArgs e)
{
e.SocketFlags = SocketFlags.None;
for (int i = 0; i < e.Buffer.Length; i++) e.Buffer[i] = 0;
e.SetBuffer(0, e.Buffer.Length);
var willRaiseEvent = e.AcceptSocket.ReceiveAsync(e);
if (!willRaiseEvent) Received(e);
}
void Process(byte[] bytes) { }
}
एमबी रैम? क्या मैं कैश हूं? मुझे उम्मीद है कि आपके पास कई जीबी मेमोरी है। क्या आपने बाधाओं को देखने के लिए संसाधन मॉनिटर या प्रोसेस एक्सप्लोरर का उपयोग किया है? – HABO
हम्म ... आपके सर्वर पर एसिंक्रोनस आर्किटेक्चर क्या है? क्या आप कुछ छद्म कोड पोस्ट कर सकते हैं ताकि यह वर्णन किया जा सके कि सुनो कैसे होता है और कनेक्शन कैसे स्वीकार किए जाते हैं आदि? –
@HABO धन्यवाद! मैंने इसे सही किया है। –