⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket.cpp

📁 A*算法 A*算法 A*算法 A*算法A*算法A*算法
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    goto exit;

  sig = (wxUint32)msg.sig[0];
  sig |= (wxUint32)(msg.sig[1] << 8);
  sig |= (wxUint32)(msg.sig[2] << 16);
  sig |= (wxUint32)(msg.sig[3] << 24);

  if (sig != 0xdeadfeed)
  {
    wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
    goto exit;
  }

  // everything was OK
  error = false;

exit:
  m_error = error;
  m_lcount = total;
  m_reading = false;
  SetFlags(old_flags);

  return *this;
}

wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
{
  // Mask read events
  m_reading = true;

  m_lcount = _Read(buffer, nbytes);
  Pushback(buffer, m_lcount);

  // If in wxSOCKET_WAITALL mode, all bytes should have been read.
  if (m_flags & wxSOCKET_WAITALL)
    m_error = (m_lcount != nbytes);
  else
    m_error = (m_lcount == 0);

  // Allow read events again
  m_reading = false;

  return *this;
}

wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
{
  // Mask write events
  m_writing = true;

  m_lcount = _Write(buffer, nbytes);

  // If in wxSOCKET_WAITALL mode, all bytes should have been written.
  if (m_flags & wxSOCKET_WAITALL)
    m_error = (m_lcount != nbytes);
  else
    m_error = (m_lcount == 0);

  // Allow write events again
  m_writing = false;

  return *this;
}

wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
{
  wxUint32 total = 0;

  // If the socket is invalid or parameters are ill, return immediately
  if (!m_socket || !buffer || !nbytes)
    return 0;

  // Possible combinations (they are checked in this order)
  // wxSOCKET_NOWAIT
  // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
  // wxSOCKET_BLOCK
  // wxSOCKET_NONE
  //
  int ret;
  if (m_flags & wxSOCKET_NOWAIT)
  {
    m_socket->SetNonBlocking(1);
    ret = m_socket->Write((const char *)buffer, nbytes);
    m_socket->SetNonBlocking(0);

    if (ret > 0)
      total = ret;
  }
  else
  {
    bool more = true;

    while (more)
    {
      if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
        break;

      ret = m_socket->Write((const char *)buffer, nbytes);

      if (ret > 0)
      {
        total  += ret;
        nbytes -= ret;
        buffer  = (const char *)buffer + ret;
      }

      // If we got here and wxSOCKET_WAITALL is not set, we can leave
      // now. Otherwise, wait until we send all the data or until there
      // is an error.
      //
      more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
    }
  }

  return total;
}

wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
{
  wxUint32 total;
  bool error;
  struct
  {
    unsigned char sig[4];
    unsigned char len[4];
  } msg;

  // Mask write events
  m_writing = true;

  error = true;
  total = 0;
  SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);

  msg.sig[0] = (unsigned char) 0xad;
  msg.sig[1] = (unsigned char) 0xde;
  msg.sig[2] = (unsigned char) 0xed;
  msg.sig[3] = (unsigned char) 0xfe;

  msg.len[0] = (unsigned char) (nbytes & 0xff);
  msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
  msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
  msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);

  if (_Write(&msg, sizeof(msg)) < sizeof(msg))
    goto exit;

  total = _Write(buffer, nbytes);

  if (total < nbytes)
    goto exit;

  msg.sig[0] = (unsigned char) 0xed;
  msg.sig[1] = (unsigned char) 0xfe;
  msg.sig[2] = (unsigned char) 0xad;
  msg.sig[3] = (unsigned char) 0xde;
  msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;

  if ((_Write(&msg, sizeof(msg))) < sizeof(msg))
    goto exit;

  // everything was OK
  error = false;

exit:
  m_error = error;
  m_lcount = total;
  m_writing = false;

  return *this;
}

wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
{
  if (nbytes != 0)
    Pushback(buffer, nbytes);

  m_error = false;
  m_lcount = nbytes;

  return *this;
}

wxSocketBase& wxSocketBase::Discard()
{
  char *buffer = new char[MAX_DISCARD_SIZE];
  wxUint32 ret;
  wxUint32 total = 0;

  // Mask read events
  m_reading = true;

  SetFlags(wxSOCKET_NOWAIT);

  do
  {
    ret = _Read(buffer, MAX_DISCARD_SIZE);
    total += ret;
  }
  while (ret == MAX_DISCARD_SIZE);

  delete[] buffer;
  m_lcount = total;
  m_error  = false;

  // Allow read events again
  m_reading = false;

  return *this;
}

// --------------------------------------------------------------------------
// Wait functions
// --------------------------------------------------------------------------

// All Wait functions poll the socket using GSocket_Select() to
// check for the specified combination of conditions, until one
// of these conditions become true, an error occurs, or the
// timeout elapses. The polling loop calls PROCESS_EVENTS(), so
// this won't block the GUI.

bool wxSocketBase::_Wait(long seconds,
                         long milliseconds,
                         wxSocketEventFlags flags)
{
  GSocketEventFlags result;
  long timeout;

  // Set this to true to interrupt ongoing waits
  m_interrupt = false;

  // Check for valid socket
  if (!m_socket)
    return false;

  // Check for valid timeout value.
  if (seconds != -1)
    timeout = seconds * 1000 + milliseconds;
  else
    timeout = m_timeout * 1000;

  bool has_event_loop = wxTheApp->GetTraits() ? (wxTheApp->GetTraits()->GetSocketGUIFunctionsTable() ? true : false) : false;

  // Wait in an active polling loop.
  //
  // NOTE: We duplicate some of the code in OnRequest, but this doesn't
  //   hurt. It has to be here because the (GSocket) event might arrive
  //   a bit delayed, and it has to be in OnRequest as well because we
  //   don't know whether the Wait functions are being used.
  //
  // Do this at least once (important if timeout == 0, when
  // we are just polling). Also, if just polling, do not yield.

  wxDateTime current_time = wxDateTime::UNow();
  unsigned int time_limit = (current_time.GetTicks() * 1000) + current_time.GetMillisecond() + timeout;
  bool done = false;
  bool valid_result = false;

  if (!has_event_loop) 
  {
    // This is used to avoid a busy loop on wxBase - having a select
    // timeout of 50 ms per iteration should be enough.
    if (timeout > 50)
      m_socket->SetTimeout(50);
    else
      m_socket->SetTimeout(timeout);
  }

  while (!done)
  {
    result = m_socket->Select(flags | GSOCK_LOST_FLAG);

    // Incoming connection (server) or connection established (client)
    if (result & GSOCK_CONNECTION_FLAG)
    {
      m_connected = true;
      m_establishing = false;
      valid_result = true;
      break;
    }

    // Data available or output buffer ready
    if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
    {
      valid_result = true;
      break;
    }

    // Connection lost
    if (result & GSOCK_LOST_FLAG)
    {
      m_connected = false;
      m_establishing = false;
      valid_result = ((flags & GSOCK_LOST_FLAG) != 0);
      break;
    }

    // Wait more?
    current_time = wxDateTime::UNow();
    int time_left = time_limit - ((current_time.GetTicks() * 1000) + current_time.GetMillisecond());
    if ((!timeout) || (time_left <= 0) || (m_interrupt))
      done = true;
    else
    {
      if (has_event_loop) 
      {
          PROCESS_EVENTS();
      }
      else 
      {
        // If there's less than 50 ms left, just call select with that timeout.
        if (time_left < 50)
          m_socket->SetTimeout(time_left);
      }
    }
  }

  // Set timeout back to original value (we overwrote it for polling)
  if (!has_event_loop)
    m_socket->SetTimeout(m_timeout*1000);

  return valid_result;
}

bool wxSocketBase::Wait(long seconds, long milliseconds)
{
  return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
                                      GSOCK_OUTPUT_FLAG |
                                      GSOCK_CONNECTION_FLAG |
                                      GSOCK_LOST_FLAG);
}

bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
{
  // Check pushback buffer before entering _Wait
  if (m_unread)
    return true;

  // Note that GSOCK_INPUT_LOST has to be explicitly passed to
  // _Wait becuase of the semantics of WaitForRead: a return
  // value of true means that a GSocket_Read call will return
  // immediately, not that there is actually data to read.

  return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
                                      GSOCK_LOST_FLAG);
}


bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
{
  return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
}

bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
{
  return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
}

// --------------------------------------------------------------------------
// Miscellaneous
// --------------------------------------------------------------------------

//
// Get local or peer address
//

bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
{
  GAddress *peer;

  if (!m_socket)
    return false;

  peer = m_socket->GetPeer();

    // copying a null address would just trigger an assert anyway

  if (!peer)
    return false;

  addr_man.SetAddress(peer);
  GAddress_destroy(peer);

  return true;
}

bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
{
  GAddress *local;

  if (!m_socket)
    return false;

  local = m_socket->GetLocal();
  addr_man.SetAddress(local);
  GAddress_destroy(local);

  return true;
}

//
// Save and restore socket state
//

void wxSocketBase::SaveState()
{
  wxSocketState *state;

  state = new wxSocketState();

  state->m_flags      = m_flags;
  state->m_notify     = m_notify;
  state->m_eventmask  = m_eventmask;
  state->m_clientData = m_clientData;

  m_states.Append(state);
}

void wxSocketBase::RestoreState()
{
  wxList::compatibility_iterator node;
  wxSocketState *state;

  node = m_states.GetLast();
  if (!node)
    return;

  state = (wxSocketState *)node->GetData();

  m_flags      = state->m_flags;
  m_notify     = state->m_notify;
  m_eventmask  = state->m_eventmask;
  m_clientData = state->m_clientData;

  m_states.Erase(node);
  delete state;
}

//
// Timeout and flags
//

void wxSocketBase::SetTimeout(long seconds)
{
  m_timeout = seconds;

  if (m_socket)
    m_socket->SetTimeout(m_timeout * 1000);
}

void wxSocketBase::SetFlags(wxSocketFlags flags)
{
  m_flags = flags;
}


// --------------------------------------------------------------------------
// Event handling
// --------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -