📄 socket.cpp
字号:
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 + -