Receiving only necessary data with C++ Socket

試著忘記壹切 提交于 2021-02-02 09:45:31

问题


I'm just trying to get the contents of a page with their headers...but it seems that my buffer of size 1024 is either too large or too small for the last packet of information coming through...I don't want to get too much or too little, if that makes sense. Here's my code. It's printing out the page just fine with all the information, but I want to ensure that it's correct.

//Build HTTP Get Request
std::stringstream ss;
ss << "GET " << url << " HTTP/1.0\r\nHost: " << strHostName << "\r\n\r\n";
std::string req = ss.str();

// Send Request
send(hSocket, req.c_str(), strlen(req.c_str()), 0);

// Read from socket into buffer.
do
{
     nReadAmount = read(hSocket, pBuffer, sizeof pBuffer);
     printf("%s", pBuffer);

}
while(nReadAmount != 0);

回答1:


 nReadAmount = read(hSocket, pBuffer, sizeof pBuffer);
 printf("%s", pBuffer);

This is broken. You can only use the %s format specifier for a C-style (zero-terminated) string. How is printf supposed to know how many bytes to print? That information is in nReadAmount, but you don't use it.

Also, you call printf even if read fails.

The simplest fix:

 do
 {
     nReadAmount = read(hSocket, pBuffer, (sizeof pBuffer) - 1);
     if (nReadAmount <= 0)
         break;
     pBuffer[nReadAmount] = 0;
     printf("%s", pBuffer);
 } while(1);



回答2:


The correct way to read an HTTP reply is to read until you have received a full LF-delimited line (some servers use bare LF even though the official spec says to use CRLF), which contains the response code and version, then keep reading LF-delimited lines, which are the headers, until you encounter a 0-length line, indicating the end of the headers, then you have to analyze the headers to figure out how the remaining data is encoded so you know the proper way to read it and know how it is terminated. There are several different possibilities, refer to RFC 2616 Section 4.4 for the actual rules.

In other words, your code needs to use this kind of structure instead (pseudo code):

// Send Request
send(hSocket, req.c_str(), req.length(), 0);

// Read Response
std::string line = ReadALineFromSocket(hSocket);
int rescode = ExtractResponseCode(line);
std::vector<std::string> headers;
do
{
     line = ReadALineFromSocket(hSocket);
     if (line.length() == 0) break;
     headers.push_back(line);
}
while (true);

if (
    ((rescode / 100) != 1) &&
    (rescode != 204) &&
    (rescode != 304) &&
    (request is not "HEAD")
)
{
    if ((headers has "Transfer-Encoding") && (Transfer-Encoding != "identity"))
    {
        // read chunks until a 0-length chunk is encountered.
        // refer to RFC 2616 Section 3.6 for the format of the chunks...
    }
    else if (headers has "Content-Length")
    {
       // read how many bytes the Content-Length header says...
    }
    else if ((headers has "Content-Type") && (Content-Type == "multipart/byteranges"))
    {
        // read until the terminating MIME boundary specified by Content-Type is encountered...
    }
    else
    {
        // read until the socket is disconnected...
    }
}


来源:https://stackoverflow.com/questions/14421008/receiving-only-necessary-data-with-c-socket

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!