मुझे वांछित मात्रा में बाइट्स भेजे जाने तक लूप में भेजने() को कॉल करने की आवश्यकता के बारे में पता है। प्राप्त करने वाले पक्ष पर भी।

मैंने लिखा आरईवी के आसपास रैपर का एक हिस्सा यहां दिया गया है:

do{
            result = socket->receiveData(m_recvBuf + recv_len , BUF_LENGTH - recv_len);
            recv_len += result;
.....

मैं कुछ चीजों को लेकर थोड़ा भ्रमित हूं, इसलिए यहां जाता है:

  1. अगर भेजें() 10 बाइट्स लौटाता है, तो क्या वे दस बाइट अभी भी प्रेषक पक्ष में हैं, लेकिन भेजे जाने के लिए तैयार हैं। या बाइट भौतिक रूप से रिसीवर कंप्यूटर पर आ गए हैं?

  2. यदि उपर्युक्त का उत्तर हां है, तो क्या recv() को कॉल करना हमेशा उन 10 बाइट्स को वापस कर देता है जैसे वे पहले ही आ चुके हैं?

  3. मैं इसे इस तरह भी रख सकता था; अगर भेजने के लिए हर बार 10 लौटने पर तीन बार कॉल किया गया है, तो कुल बाइट्स को 30 माना जाता है। क्या आरईवी() को कॉल करना, एक बार, 30 बाइट्स लौटाता है?

प्रश्न 1. "अभी भी केवल रिसीवर की तरफ" के रूप में संपादित "अभी भी केवल प्रेषक पक्ष में" होना चाहिए।

परिदृश्य: पीसी 1 कॉल में मेरा प्रोग्राम भेजें (); भेजें () रिटर्न 1; मेरा कोड चीजें जो एक बाइट को पीसी 2 में रिसीवर प्रोग्राम में भेजा गया है। मेरे भेजने () फ़ंक्शन के वापस आने के तुरंत बाद नेटवर्क केबल एक कुत्ते द्वारा खा लिया गया।

अगर वास्तविक जीवन में ऐसा है, तो मैंने निश्चित रूप से टीसीपी बनाम यूडीपी के लाभों को गलत समझा है।

उत्तर देने में समय देने के लिए सभी का धन्यवाद।

0
Ipraks 12 पद 2017, 14:25

3 जवाब

सबसे बढ़िया उत्तर

अगर भेजें() 10 बाइट्स लौटाता है, तो क्या वे दस बाइट अभी भी प्रेषक पक्ष में हैं, लेकिन भेजे जाने के लिए तैयार हैं। या बाइट भौतिक रूप से रिसीवर कंप्यूटर पर आ गए हैं?

आप यह नहीं बता सकते हैं कि 10 बाइट्स वास्तव में कहां हैं, उनमें से कुछ भेजने वाली मशीन में कहीं प्रतीक्षा कर रहे हैं, कुछ तार पर और कुछ प्राप्त करने वाली मशीन में कहीं प्रतीक्षा कर रहे हैं।

यदि उपर्युक्त का उत्तर हां है, तो क्या recv() को कॉल करना हमेशा उन 10 बाइट्स को वापस कर देता है जैसे वे पहले ही आ चुके हैं?

एन/ए

मैं इसे इस तरह भी रख सकता था; अगर भेजने के लिए हर बार 10 लौटने पर तीन बार कॉल किया गया है, तो कुल बाइट्स को 30 माना जाता है। क्या आरईवी (), एक बार कॉल करना, 30 बाइट्स लौटाता है?

आप नहीं बता सकते! टीसीपी मोड में आप केवल यही कह सकते हैं कि बाइट्स उसी क्रम में प्राप्त होते हैं जिस क्रम में उन्हें भेजा जा रहा है।

परिदृश्य: पीसी 1 कॉल में मेरा प्रोग्राम भेजें (); भेजें () रिटर्न 1; मेरा कोड चीजें जो एक बाइट को पीसी 2 में रिसीवर प्रोग्राम में भेजा गया है। मेरे भेजने () फ़ंक्शन के वापस आने के तुरंत बाद नेटवर्क केबल एक कुत्ते द्वारा खा लिया गया।

तब तुम कुछ नहीं कह सकते...

अगर वास्तविक जीवन में ऐसा है, तो मैंने निश्चित रूप से टीसीपी बनाम यूडीपी के लाभों को गलत समझा है।

यूडीपी डेटाग्राम-उन्मुख सिमेंटिक है, जैसे डाक प्रणाली (कोई संरक्षित आदेश नहीं, किसी भी प्रकार की कोई गारंटी नहीं, हानि संभव है, डुप्लिकेट, आदि)

टीसीपी स्ट्रीम-ओरिएंटेड सिमेंटिक है, जैसे फोन सिस्टम (संरक्षित ऑर्डर और नो लॉस)।

बेशक हार्ड नेटवर्क की विफलता के मामले में, टीसीपी कुछ भी सुनिश्चित नहीं कर सकता है!

चूंकि टीसीपी आईपी (डेटाग्राम) के शीर्ष पर बनाया गया है, जो टीसीपी पर भेजा जाता है, आईपी के माध्यम से भेजने के लिए खंडित होता है, और आप इस तरह के विखंडन को नियंत्रित नहीं करते हैं (मैं कैशिंग आदि के बारे में बताना भूल गया)।

0
Jean-Baptiste Yunès 14 पद 2017, 19:21

यदि भेजें () x बाइट्स देता है, तो क्या recv () को एक कॉल में समान मात्रा में बाइट्स मिलते हैं?

सामान्य तौर पर, निश्चित रूप से नहीं !!

उदाहरण के लिए, TCP/IP सॉकेट के लिए (देखें tcp(7) और socket(7)) वाईफाई राउटर और/या इंटरकांटिनेंटल राउटर से गुजरते हुए, पैकेट को खंडित और/या फिर से जोड़ा जा सकता है। तो एक दिया गया send कई recv के अनुरूप हो सकता है और इसके विपरीत, और संदेशों की "सीमाओं" का सम्मान नहीं किया जाता है। इसलिए, अनुप्रयोगों के लिए, टीसीपी बिना किसी संदेश सीमा के बाइट्स की धारा है। स्लाइडिंग विंडो प्रोटोकॉल और TCP कंजेशन कंट्रोल TCP के अंदर उपयोग किया जाता है।

व्यवहार में, आप देख सकते हैं, उदा। एक ही ईथरनेट केबल पर दो कंप्यूटरों के बीच, कि पैकेट खंडित या पुन: एकत्रित नहीं होते हैं। लेकिन आपको उस परिकल्पना के साथ कोड नहीं करना चाहिए।

सीधे तौर पर, अनुप्रयोग स्तर प्रोटोकॉल जैसे HTTP या SMTP या JSONRPC< /a> या X11 प्रोटोकॉल को संदेश सीमाओं और सर्वर और दोनों सर्वरों को परिभाषित करने के लिए डिज़ाइन किया जाना चाहिए क्लाइंट पक्षों को बफरिंग करनी चाहिए

आप poll(2) का उपयोग करना चाहेंगे, देखें यह उत्तर

यदि भेजें () 10 बाइट्स लौटाता है, तो क्या वे दस बाइट्स अभी भी केवल रिसीवर की तरफ हैं, लेकिन भेजे जाने के लिए तैयार हैं।

यह परिभाषित करना आसान नहीं है कि "रिसीवर साइड में अभी भी" का वास्तव में क्या मतलब है (क्योंकि आप वास्तव में इस बात की परवाह नहीं करते हैं कि कर्नेल के अंदर, या नेटवर्क कंट्रोलर के अंदर, या इंटरकांटिनेंटल केबल पर क्या होता है)। अतः उपरोक्त वाक्य अर्थहीन है।

आपके एप्लिकेशन कोड को केवल सिस्टम कॉल की परवाह होनी चाहिए (syscalls(2)...) जैसे पोल(2), send(2) और संबंधित, लिखें(2), recv(2) और संबंधित, पढ़ें (2), socket(2) , स्वीकार करें(2), connect(2), bind(2) आदि...

आप 0mq जैसी मैसेजिंग लाइब्रेरी का उपयोग करना चाह सकते हैं।

मेरे भेजने () फ़ंक्शन के वापस आने के तुरंत बाद नेटवर्क केबल एक कुत्ते द्वारा खा लिया गया।

आप ऐसे परिदृश्य की इतनी परवाह क्यों करते हैं। आपका कुत्ता आपका लैपटॉप भी गिरा सकता है, या उस पर पेशाब कर सकता है। एक बार send ने आपके आवेदन को बता दिया है कि दस बाइट उत्सर्जित हो चुके हैं, तो आपको अपने कर्नेल पर भरोसा करना चाहिए। लेकिन प्राप्त करने वाले प्रोग्राम ने अभी तक इन बाइट्स को प्राप्त नहीं किया है (दूसरे महाद्वीप पर, आपको दर्जनों मिलीसेकंड प्रतीक्षा करने की आवश्यकता होगी, जो कि कंप्यूटर के लिए काफी बड़ी देरी है)। शायद, दस बाइट समुद्र के बीच में होते हैं जब आपके कुत्ते ने आपके ईथरनेट केबल को काट लिया है (और आप यथोचित कोड कर सकते हैं जैसे कि वे उत्सर्जित हो गए हों)। टीसीपी प्रोटोकॉल यह पता लगाएगा कि लिंक बाधित हो गया है, लेकिन वह त्रुटि आपके प्रोग्राम को बहुत बाद में दी जाएगी (शायद अगले कॉल के लिए send के दस सेकंड बाद होने वाली त्रुटि के रूप में) .

(टीसीपी परिभाषा में कुछ बड़े मैक्रोस्कोपिक देरी हैं, शायद 128 सेकंड के रूप में बड़े-मैं विवरण भूल गया- और ये देरी इंटरप्लानेटरी संचार के लिए बहुत छोटी हैं, इसलिए टीसीपी का उपयोग मंगल ग्रह पर नहीं किया जा सकता है)

आपको (ज्यादातर समय) केवल सिस्टम कॉल स्तर पर तर्क करना चाहिए।

(बेशक, कुछ मामलों में - दूरस्थ न्यूरोसर्जिकल रोबोट के बारे में सोचें- जो पर्याप्त नहीं हो सकता है)

मैंने निश्चित रूप से टीसीपी बनाम यूडीपी के लाभों को गलत समझा है।

यदि आपने अभी-अभी UDP का उपयोग किया है, तो दिए गए पैकेट को खंडित किया जा सकता है, खोया जा सकता है या कई बार प्राप्त किया जा सकता है। टीसीपी के साथ, यह यथोचित रूप से नहीं हो सकता है (कम से कम जब अगले पैकेट सफलतापूर्वक भेजे और प्राप्त किए गए हों)।

1
Basile Starynkevitch 12 पद 2017, 16:25

मेरा आदर्श वाक्य: "यदि संदेह है, तो इसे आजमाएं"।

यह एक पूरा प्रोग्राम है जो दर्शाता है कि मेरी मशीन पर, दस लाख बाइट्स का एक पूरा पैकेट अलग-अलग रीड में बफर किए बिना लूपबैक एडेप्टर के माध्यम से भी नहीं बनाता है (और संभवतः लिखता है, क्योंकि मैंने समग्र फ़ंक्शन का उपयोग किया है asio::write() :

#include <thread>
#include <mutex>
#include <condition_variable>
#include <boost/asio.hpp>
#include <boost/system/error_code.hpp>
#include <vector>
#include <iostream>

namespace asio
{
    using namespace boost::asio;
    using boost::system::error_code;
}

using protocol = asio::ip::tcp;

struct event
{
    std::mutex mutex;
    std::condition_variable cv;
    bool notified = false;

    void notify()
    {
        auto lock = std::unique_lock<std::mutex>(mutex);
        notified = true;
        lock.unlock();
        cv.notify_all();
    }

    void wait()
    {
        auto lock = std::unique_lock<std::mutex>(mutex);
        cv.wait(lock, [this] { return this->notified; });
    }
};

struct emitter
{
    emitter(std::ostream& os) : os(os) {}

    template<class...Ts>
    void operator()(Ts&&...ts)
    {
        auto lock = std::unique_lock<std::mutex>(m);
        auto emit_item = [&os = this->os](auto&& x)
        {
            os << x;
        };
        using expand = int[];
        void(expand { 0,
            (emit_item(ts),0)...
        });
        os << std::endl;
    }

    std::ostream& os;
    std::mutex m;
};

event rx_ready;
emitter stdout_emit { std::cout };

void sender()
{
    asio::io_service executor;

    auto big_buffer = std::vector<char>(1000000, 'a');
    protocol::socket sock(executor);
    rx_ready.wait();
    asio::error_code ec;
    if(sock.connect(protocol::endpoint(asio::ip::address_v4(0x7f000001), 12345)), ec) {
        stdout_emit("connect failure: ", ec.message());
        return;
    }
    auto written = asio::write(sock, asio::buffer(big_buffer), ec);
    stdout_emit("wrote: ", written);
    if (ec) {
        stdout_emit("write failure: ", ec.message());
    }
    sock.shutdown(protocol::socket::shutdown_send, ec);
    if (ec) {
        stdout_emit("shutdown failure: ", ec.message());
    }
    sock.close(ec);
    if (ec) {
        stdout_emit("close failure: ", ec.message());
    }
}

void start_receiving(protocol::socket& s)
{
    auto huge_buffer_ptr = std::make_shared<std::vector<char>>(1000000);

    s.async_read_some(asio::buffer(*huge_buffer_ptr), [huge_buffer_ptr, &s](asio::error_code ec, std::size_t size)
    {
        stdout_emit("read ", size, " bytes");
        if (ec)
        {
            stdout_emit("read error: ", ec.message());
        }
        else
        {
            start_receiving(s);
        }
    });
}

void receiver()
{
    asio::io_service executor;
    protocol::acceptor acceptor(executor);
    auto ep = protocol::endpoint(protocol::v4(), 12345);
    acceptor.open(ep.protocol());
    acceptor.bind(ep);
    acceptor.listen();

    protocol::socket s(executor);
    acceptor.async_accept(s, [&](asio::error_code ec){
        if (ec) {
            stdout_emit("accept: ", ec.message());
        }
        else
        {
            start_receiving(s);
        }
    });
    rx_ready.notify();
    executor.run();
}

int main()
{
    auto t = std::thread(receiver);

    sender();

    t.join();
}

नमूना परिणाम:

read 393216 bytes
wrote: 1000000
read 606784 bytes
read 0 bytes
read error: End of file

Process finished with exit code 0

पढ़ने और लिखने वाले बफ़र्स को 10,000,000 बाइट्स में बदलने से मुझे यह मिला:

read 393216 bytes
read 638820 bytes
read 639028 bytes
read 639028 bytes
read 639028 bytes
read 638820 bytes
read 639028 bytes
read 639028 bytes
read 639028 bytes
read 638820 bytes
read 639028 bytes
read 639028 bytes
read 639028 bytes
read 638820 bytes
wrote: 10000000
read 639028 bytes
read 639028 bytes
read 22196 bytes
read 0 bytes
read error: End of file

Process finished with exit code 0
0
Richard Hodges 12 पद 2017, 17:49