📄 cfsocket.cpp
字号:
{ if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() ) break; ret = GSocket_Write(m_socket, (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;#if !defined(wxUSE_GUI) || !wxUSE_GUI GSocket_SetTimeout(m_socket, timeout);#endif // 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. wxStopWatch chrono; bool done = false; while (!done) { result = GSocket_Select(m_socket, flags | GSOCK_LOST_FLAG); // Incoming connection (server) or connection established (client) if (result & GSOCK_CONNECTION_FLAG) { m_connected = true; m_establishing = false; return true; } // Data available or output buffer ready if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG)) { return true; } // Connection lost if (result & GSOCK_LOST_FLAG) { m_connected = false; m_establishing = false; return (flags & GSOCK_LOST_FLAG) != 0; } // Wait more? if ((!timeout) || (chrono.Time() > timeout) || (m_interrupt)) done = true; else PROCESS_EVENTS(); } return false;}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 = GSocket_GetPeer(m_socket); // 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{#if 0 GAddress *local; if (!m_socket) return false; local = GSocket_GetLocal(m_socket); addr_man.SetAddress(local); GAddress_destroy(local);#endif 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 0 if (m_socket) GSocket_SetTimeout(m_socket, m_timeout * 1000);#endif}void wxSocketBase::SetFlags(wxSocketFlags flags){ m_flags = flags;}// --------------------------------------------------------------------------// Event handling// --------------------------------------------------------------------------// A note on how events are processed, which is probably the most// difficult thing to get working right while keeping the same API// and functionality for all platforms.//// When GSocket detects an event, it calls wx_socket_callback, which in// turn just calls wxSocketBase::OnRequest in the corresponding wxSocket// object. OnRequest does some housekeeping, and if the event is to be// propagated to the user, it creates a new wxSocketEvent object and// posts it. The event is not processed immediately, but delayed with// AddPendingEvent instead. This is necessary in order to decouple the// event processing from wx_socket_callback; otherwise, subsequent IO// calls made from the user event handler would fail, as gtk callbacks// are not reentrant.//// Note that, unlike events, user callbacks (now deprecated) are _not_// decoupled from wx_socket_callback and thus they suffer from a variety// of problems. Avoid them where possible and use events instead.extern "C"void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket), GSocketEvent notification, char *cdata){ wxSocketBase *sckobj = (wxSocketBase *)cdata; sckobj->OnRequest((wxSocketNotify) notification);}void wxSocketBase::OnRequest(wxSocketNotify notification){ // NOTE: We duplicate some of the code in _Wait, 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 _Wait as well because we don't // know whether the Wait functions are being used. switch (notification) { case wxSOCKET_CONNECTION: m_establishing = false; m_connected = true; break; // If we are in the middle of a R/W operation, do not // propagate events to users. Also, filter 'late' events // which are no longer valid. case wxSOCKET_INPUT: if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG)) return; break; case wxSOCKET_OUTPUT: if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG)) return; break; case wxSOCKET_LOST: m_connected = false; m_establishing = false; break; default: break; } // Schedule the event wxSocketEventFlags flag = 0; wxUnusedVar(flag); switch (notification) { case GSOCK_INPUT: flag = GSOCK_INPUT_FLAG; break; case GSOCK_OUTPUT: flag = GSOCK_OUTPUT_FLAG; break; case GSOCK_CONNECTION: flag = GSOCK_CONNECTION_FLAG; break; case GSOCK_LOST: flag = GSOCK_LOST_FLAG; break; default: wxLogWarning( wxT("wxSocket: unknown event!") ); return; } if (((m_eventmask & flag) == flag) && m_notify) { if (m_handler) { wxSocketEvent event(m_id); event.m_event = notification; event.m_clientData = m_clientData; event.SetEventObject(this); m_handler->AddPendingEvent(event); } }}void wxSocketBase::Notify(bool notify){ m_notify = notify;}void wxSocketBase::SetNotify(wxSocketEventFlags flags){ m_eventmask = flags;}void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id){ m_handler = &handler; m_id = id;}// --------------------------------------------------------------------------// Pushback buffer// --------------------------------------------------------------------------void wxSocketBase::Pushback(const void *buffer, wxUint32 size){ if (!size) return; if (m_unread == NULL) m_unread = malloc(size); else { void *tmp; tmp = malloc(m_unrd_size + size); memcpy((char *)tmp + size, m_unread, m_unrd_size); free(m_unread); m_unread = tmp; } m_unrd_size += size; memcpy(m_unread, buffer, size);}wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek){ if (!m_unrd_size) return 0; if (size > (m_unrd_size-m_unrd_cur)) size = m_unrd_size-m_unrd_cur; memcpy(buffer, (char *)m_unread + m_unrd_cur, size); if (!peek) { m_unrd_cur += size; if (m_unrd_size == m_unrd_cur) { free(m_unread); m_unread = NULL; m_unrd_size = 0; m_unrd_cur = 0; } } return size;}// ==========================================================================// wxSocketServer// ==========================================================================// --------------------------------------------------------------------------// Ctor// --------------------------------------------------------------------------wxSocketServer::wxSocketServer(wxSockAddress& addr_man, wxSocketFlags flags) : wxSocketBase(flags, wxSOCKET_SERVER){ wxLogTrace( wxTRACE_Socket, wxT("Opening wxSocketServer") ); m_socket = GSocket_new(); if (!m_socket) { wxLogTrace( wxTRACE_Socket, wxT("*** GSocket_new failed") ); return; } // Setup the socket as server#if 0 GSocket_SetLocal(m_socket, addr_man.GetAddress()); if (GSocket_SetServer(m_socket) != GSOCK_NOERROR) { GSocket_destroy(m_socket); m_socket = NULL; wxLogTrace( wxTRACE_Socket, wxT("*** GSocket_SetServer failed") ); return; } GSocket_SetTimeout(m_socket, m_timeout * 1000); GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG | GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG, wx_socket_callback, (char *)this);#endif}// --------------------------------------------------------------------------// Accept// --------------------------------------------------------------------------bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait){ GSocket *child_socket; if (!m_socket) return false; // If wait == false, then the call should be nonblocking. // When we are finished, we put the socket to blocking mode // again.#if 0 if (!wait) GSocket_SetNonBlocking(m_socket, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -