हमारे पास दो क्यूटी अनुप्रयोग हैं। ऐप 1 एप 2 से QTcpServer
से कनेक्शन स्वीकार करता है और इसे QTcpSocket* tcpSocket
के उदाहरण में संग्रहीत करता है। ऐप 1 30 हर्ट्ज के साथ सिमुलेशन चलाता है। प्रत्येक सिमुलेशन रन के लिए, एक QByteArray
कुछ किलोबाइट से मिलकर (मुख्य/जीयूआई धागे से) निम्नलिखित कोड का उपयोग कर भेज दिया जाता है:छोटे डेटा पैकेजों को लगातार भेजने के लिए QTcpSocket का उपयोग कैसे करें?
QByteArray block;
/* lines omitted which write data into block */
tcpSocket->write(block, block.size());
tcpSocket->waitForBytesWritten(1);
रिसीवर सॉकेट QTcpSocket :: readDataBlock संकेत को सुनता है (मुख्य/जीयूआई में धागा) और जीयूआई के लिए इसी समय टिकट मुद्रित करता है।
जब दोनों एप 1 और ऐप 2 एक ही सिस्टम पर चलते हैं, तो संकुल पूरी तरह सिंक हो जाते हैं। हालांकि जब नेटवर्क के माध्यम से जुड़े विभिन्न सिस्टम पर App1 और App2 चलाए जाते हैं, तो App2 अब App2 में सिमुलेशन के साथ समन्वयित नहीं होता है। पैकेज बहुत धीमे हो जाते हैं। और भी आश्चर्यजनक (और हमारे कार्यान्वयन को इंगित करना गलत है) यह तथ्य है कि जब हम सिमुलेशन लूप को रोकते हैं, तो कोई और पैकेज प्राप्त नहीं होता है। यह हमें आश्चर्यचकित करता है, क्योंकि हम टीसीपी प्रोटोकॉल से अपेक्षा करते हैं कि सभी पैकेज अंततः आ जाएंगे।
हमने क्यूटी के fortune example पर आधारित टीसीपी तर्क बनाया है। हालांकि, भाग्य सर्वर अलग है, क्योंकि यह केवल आने वाले क्लाइंट के लिए एक पैकेज भेजता है। क्या कोई पहचान सकता है कि हमने क्या गलत किया है?
नोट: हम MSVC2012 (App1), MSVC2010 (App2) और Qt 5.2 का उपयोग करते हैं।
संपादित करें: एक पैकेज मैं एक ही अनुकरण प्रयोग है, जो संख्या का एक समूह है, QByteArray block
में लिखा का परिणाम मतलब के साथ। हालांकि, पहले बिट्स में QByteArray की लंबाई होती है, ताकि ग्राहक जांच सके कि सभी डेटा प्राप्त हुए हैं या नहीं।
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_5_2);
if (blockSize == 0) {
if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
return; // cannot yet read size from data block
in >> blockSize; // read data size for data block
}
// if the whole data block is not yet received, ignore it
if (tcpSocket->bytesAvailable() < blockSize)
return;
// if we get here, the whole object is available to parse
QByteArray object;
in >> object;
blockSize = 0; // reset blockSize for handling the next package
return;
टीसीपी संकुल/पैकेट नहीं है - यह सिर्फ एक बाइट धारा है। आपने डेटा को कैसे कटाया है? यानी आपके प्राप्तकर्ता आवेदन को कैसे पता चलेगा जब आपके अपने 1 डेटा "पैकेट" शुरू होते हैं और दूसरा अंत होता है?इसके अलावा, टीसीपी का प्रवाह नियंत्रण होता है, इसलिए यदि आप डेटा पढ़ना बंद कर देते हैं, तो टीसीपी स्टैक में बफर भर जाते हैं, और कोई और डेटा नहीं भेजा जाएगा (और प्रेषक तब तक ब्लॉक करेगा जब तक कि आपके सॉकेट गैर-अवरोध मोड में न हों)। यह अनुमान लगाने में बहुत मुश्किल है कि आप क्या गलत करते हैं जब हम नहीं जानते कि आप क्या करते हैं, या आप सिमुलेशन कैसे काम करते हैं या यह किसी भी तरह से "सिंक से बाहर" कैसे बनता है – nos
मैंने अपने मूल प्रश्न को संपादित करके अपने प्रश्न का उत्तर देने का प्रयास किया। कृपया इसे देखें। –
ऐसा लगता है कि आप जो चाहते हैं उससे अधिक डेटा पढ़ने का जोखिम लेते हैं, उदाहरण के लिए आपका ब्लॉकइज़ 1024 है लेकिन 'tcpSocket-> बाइट्स उपलब्ध()' 1222 बाइट उपलब्ध है, तो आप इसे अगले दिखने के साथ भी अगले ब्लॉक की शुरुआत पढ़ते हैं - तो आपको शायद 'in.readBytes() का उपयोग करना होगा 'इसके बजाय, जहां आप निर्दिष्ट कर सकते हैं कि कितना पढ़ना है। (और बाद में सत्यापित करें कि यह वास्तव में उस डेटा को पढ़ता है)। हालांकि यह भी निर्भर करता है कि आपका प्रोटोकॉल कैसा है। यदि उदा। यह एक साधारण अनुरोध/उत्तर है, जहां आपका प्रेषक * कभी भी * पिछले पैकेट के लिए कोई जवाब प्राप्त नहीं होने तक कोई डेटा भेजता है, वर्तमान कोड ठीक लगता है – nos