簡體   English   中英

套接字服務器以緩沖區大小接收數據

[英]Socket server receiving data at buffer size

我一個接一個地發送不同大小的數據包,如何以我發送的大小分別接收數據包,而不是在緩沖區中累積。 似乎現在服務器添加到緩沖區直到它填滿它然后我可以處理它們。

例子:

緩沖區大小:84。

從客戶端發送:84 字節、76 字節、76 字節、80 字節

在服務器中接收:84 字節、84 字節、84 字節、64 字節。

我想在發送它們時收到它們。 可能嗎?

    int port = stoi(getConfig("server_port"));
    std::string ipAddress = getConfig("ip_address");

    // Create a socket
    int listening = socket(AF_INET, SOCK_STREAM, 0);
    if (listening < 0){
        std::cerr << "Can't create a socket!" << endl;
        Logger("Can't create a socket!");
        exit(-1);
    }
    std::cout << "The socket server was created successfully." << endl;

    // Bind the socket to a IP / port
    sockaddr_in hint;
    hint.sin_family = AF_INET;
    hint.sin_port = htons(port);
    inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);

    if (bind(listening, (sockaddr*)&hint, sizeof(hint)) < 0){
        cerr << "Can't bind to IP/port!" << endl;
        Logger("Can't bind to IP/port!");
        exit(-1);
    }

    // Mark the socket for listening in
    if (listen(listening, SOMAXCONN) < 0){
        cerr << "Can't listen!" << endl;
        Logger("Can't listen!");
        exit(-1);
    }

    // Accept a call
    sockaddr_in client;
    socklen_t clientSize = sizeof(client);
    char host[NI_MAXHOST];
    char svc[NI_MAXSERV];

    while(true){
        int clientSoket = accept(listening, (sockaddr*)&client, &clientSize);
        if(clientSoket < 0){
            cerr << "Problem with client connecting!" << endl;
            Logger("Problem with client connecting!");
            break;
        }
        cout << "The client whas conected successfully." << endl;

        memset(host, 0, NI_MAXHOST);
        memset(svc, 0, NI_MAXSERV);

        int result = getnameinfo((sockaddr*)&client, clientSize, host, NI_MAXHOST, svc, NI_MAXSERV, 0);
        if(result == 0) {
            cout << host << " connected on " << svc << endl;
        } else {
            inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
            cout << host << " connected on " << ntohs(client.sin_port) << endl;
        }

        // While receiving
        char buff[84];
        while(true){
            // Clear the buffer
            memset(buff, 0, sizeof(buff));

            // Wait for a message
            int bytesRecv = recv(clientSoket, buff, sizeof(buff), 0);
            if(bytesRecv < 0){
                cerr << "There was a connection issue!" << endl;
                Logger("There was a connection issue!");
                break;
            }

            if(bytesRecv == 0){
                cout << "The client disconnected." << endl;
                Logger("The client disconnected");
                break;
            }

            cout << "bytesRecv: " << bytesRecv << endl;
       }

       // Close the socket
       close(clientSoket);
    }

不,stream sockets 不能那樣工作。

stream 套接字是一個非結構化字節 stream,無論如何都沒有任何結構。 在這方面,它與普通文件沒有什么不同。 如果您將不同大小的記錄寫入一個普通文件,並且您現在准備將它們讀回,您希望如何讀取可變大小的記錄?

無論您在此處給出哪個答案,相同的答案都適用於 sockets,此外,套接字上的read()無法保證您將閱讀多少,除非它小於或等於read()size參數。 這是您從read()獲得的唯一保證。

如果發送者調用write()兩次(順便說一句,sockets 也不能保證無論你write多少,寫多少, write也可以返回小於或等於其size參數的字節數,並且由您的代碼決定如何處理它),一旦寫入 76 個字節,第二次寫入 84 個字節, read()會讀取(假設緩沖區大小足夠大)可以讀取 1 到 160 之間的任意數量的字節字節,在初始讀取。

如果您希望實現某種正式的結構、某種記錄,則由您自己決定如何在這些約束條件下實現它。 也許通過發送每條記錄的大小(以字節為單位),然后是記錄本身。 或者做任何你想做的事。 請記住,您無法保證個人read()返回多少。 例如,如果您首先發送記錄計數,作為四字節值。 您的初始read()可能會返回一個、兩個或三個字節。 您的代碼必須准備好處理任何不測事件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM