wxSocketClient Peek not filling buffer

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
pvn
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Dec 26, 2016 5:21 am
Contact:

wxSocketClient Peek not filling buffer

Post by pvn »

I am using a wxSocketClient to read some data, and the read function works fine, say

Code: Select all

wxSocketClient socket;
socket.SetFlags(wxSOCKET_NONE);
.....

 wxCharBuffer buf(1024);
 socket.Read(buf.data(), 1024);
however when I try Peek to peek at some HTTP headers, no data is returned

Code: Select all

socket.Peek(buf.data(), 1024);
The Peek documentation say
The exact behaviour of Peek() depends on the combination of flags being used. For a detailed explanation, see SetFlags()
but it does not explain which flags should be used for Peek, and the ones I tried did not get any result.

Debugging the Peek function (Windows), in

Code: Select all

wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)

...

  const int ret = !m_impl->m_stream || m_connected
                            ? m_impl->Read(buffer, nbytes)
                            : 0;
        if ( ret == -1 )
        {
            if ( m_impl->GetLastError() == wxSOCKET_WOULDBLOCK )
            {
                // if we don't want to wait, just return immediately
                if ( m_flags & wxSOCKET_NOWAIT_READ )
                {
                    // this shouldn't be counted as an error in this case
                    SetError(wxSOCKET_NOERROR);
ret is -1 and it falls on the

Code: Select all

 SetError(wxSOCKET_NOERROR);
part
pvn
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Dec 26, 2016 5:21 am
Contact:

Re: wxSocketClient Peek not filling buffer

Post by pvn »

I also tried
GetSocket ()

http://docs.wxwidgets.org/3.1.0/classwx ... _base.html

to get the socket descriptor so I can parse the HTTP headers "manually" (i.e without the class functions, using sockets API)
but the recv fails with -1

I use this code, that works fine on my own implementation of a sockets library

https://github.com/pedro-vicente/lib_netsockets

Code: Select all

/////////////////////////////////////////////////////////////////////////////////////////////////////
//socket_t::parse_http_headers
//MSG_PEEK
//Peeks at an incoming message.The data is treated as unread and the next recv() or similar 
//function shall still return this data.
/////////////////////////////////////////////////////////////////////////////////////////////////////

int socket_t::parse_http_headers(std::string &http_headers)
{
  int recv_size; // size in bytes received or -1 on error 
  const int size_buf = 4096;
  char buf[size_buf];

  if ((recv_size = recv(m_socket_fd, buf, size_buf, MSG_PEEK)) == -1)
  {
    std::cout << "recv error: " << strerror(errno) << std::endl;
    return -1;
  }

  std::string str(buf);
  size_t pos = str.find("\r\n\r\n");

  if (pos == std::string::npos)
  {
    std::cout << "HTTP header bad format" << std::endl;
    return -1;
  }

  std::string str_headers(str.substr(0, pos + 4));
  int header_len = static_cast<int>(pos + 4);

  std::cout << str_headers.c_str() << std::endl;

  //now get headers with the obtained size from socket
  if ((recv_size = recv(m_socket_fd, buf, header_len, 0)) == -1)
  {
    std::cout << "recv error: " << strerror(errno) << std::endl;
    return -1;
  }

  //sanity check
  std::string str1(buf);
  assert(str1 == str);
  http_headers = str_headers;
  return 0;
}

Ruro
Experienced Solver
Experienced Solver
Posts: 83
Joined: Wed May 23, 2007 2:20 pm
Location: Verona, Italy

Re: wxSocketClient Peek not filling buffer

Post by Ruro »

Hi

The function, should return the available bytes that are ready when you call it.

But if there are none, the function return immediately and query LastCount() should give you 0.

The flags, probably refer to: wxSOCKET_WAITALL will only return when it has read or written ALL the data.

If you set this flag, that function peek, return only if there are some data to be read.

Best Regards,

Nicola.
pvn
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Dec 26, 2016 5:21 am
Contact:

Re: wxSocketClient Peek not filling buffer

Post by pvn »

@Ruro

yes, Peek returns 0 because there is nothing to read at that time.

The server does at some point in time

Code: Select all

socket->Write(str_response.c_str(), str_response.size());
This is my client code, that returns 0 on the Peek, even with the wxSOCKET_WAITALL flag.

The problem is that the client has to know somehow that that server has sent "Write" bytes.
Somehow the "Read" call below works, because it knows that that is data on the socket.
but the "Peek" does not seem to know

Code: Select all

 wxCharBuffer buf(1024);
  m_client->SetFlags(wxSOCKET_WAITALL);
  m_client->Peek(buf.data(), 1024);
  wxString str_header(buf.data(), m_client->LastCount());

  m_client->Read(buf.data(), 1024);
  size_t size_read = m_client->LastCount();
  wxString str_response(buf.data(), size_read);
  wxLogDebug("read %d\n%s", (int)size_read, str_response.c_str());
pvn
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Dec 26, 2016 5:21 am
Contact:

Re: wxSocketClient Peek not filling buffer

Post by pvn »

The Peek gets data if I call "WaitForRead"

Code: Select all

m_client->WaitForRead(10);
m_client->Peek(buf.data(), 1024);
but this is not a good way to do things, in real life we don't know at what time the server will send data
pvn
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Dec 26, 2016 5:21 am
Contact:

Re: wxSocketClient Peek not filling buffer

Post by pvn »

hmm, ok, it seems "WaitForRead" does not block , so Peek will get filled when the socket has data (when received from the "write")
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxSocketClient Peek not filling buffer

Post by doublemax »

I still don't see what you need Peek() for. A client-server connection like this is like a phone call, you can never know if the other side is done talking or if it will send more data. If you just want to transfer a string, you should send it together with the terminating null-byte and on the receiving end you read until you get the null-byte. Then you know it's complete.
Use the source, Luke!
pvn
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Dec 26, 2016 5:21 am
Contact:

Re: wxSocketClient Peek not filling buffer

Post by pvn »

@doublemax

I need to use Peek because I am using HTTP for a server/client.
This is the HTTP header the server sends.
After the header there is some JSON data.

Code: Select all

HTTP/1.1 200 OK
Accept: application/json
Content-Type: application/json
Content-Length: 10916433

The Peek has 2 purposes:
1) To get the length of the header.
2) To get the length of the body.

The length of the header is obtained by parsing the string until \r\n\r\n is found.
The length of the body is
Content-Length: 10916433

If this was not HTTP I could use other ways to detect the end of the data, like the C end of string you mentioned, or what I usually do is to send the size first.

For example if I want to send JSON data that has a size 1024 bytes, I do as header

Code: Select all

1024#
then on the other end I do a Peek and detect the terminator "#" and the number of characters before the #, and parse to a number 1024.

Probably I could do a Read instead of a Peek, but then I would have to keep track of the bytes read, I think it's simpler just to Peek before.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxSocketClient Peek not filling buffer

Post by doublemax »

Wouldn't it be easier to use wxHTTP then?
Use the source, Luke!
pvn
Earned some good credits
Earned some good credits
Posts: 105
Joined: Mon Dec 26, 2016 5:21 am
Contact:

Re: wxSocketClient Peek not filling buffer

Post by pvn »

@doublemax

yes, maybe, I'll give a try to wxHTTP
Post Reply