add wxSocket::IsClosed(), use it to implement Eof() in wxSocketStream

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54590 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-07-12 02:28:12 +00:00
parent 74a50e4923
commit c91574928d
4 changed files with 91 additions and 41 deletions

View File

@@ -113,6 +113,7 @@ public:
bool Ok() const { return IsOk(); } bool Ok() const { return IsOk(); }
bool IsOk() const { return (m_socket != NULL); } bool IsOk() const { return (m_socket != NULL); }
bool Error() const { return m_error; } bool Error() const { return m_error; }
bool IsClosed() const { return m_closed; }
bool IsConnected() const { return m_connected; } bool IsConnected() const { return m_connected; }
bool IsData() { return WaitForRead(0, 0); } bool IsData() { return WaitForRead(0, 0); }
bool IsDisconnected() const { return !IsConnected(); } bool IsDisconnected() const { return !IsConnected(); }
@@ -199,6 +200,8 @@ private:
bool m_reading; // busy reading? bool m_reading; // busy reading?
bool m_writing; // busy writing? bool m_writing; // busy writing?
bool m_error; // did last IO call fail? bool m_error; // did last IO call fail?
bool m_closed; // was the other end closed?
// (notice that m_error is also set then)
wxUint32 m_lcount; // last IO transaction size wxUint32 m_lcount; // last IO transaction size
unsigned long m_timeout; // IO timeout value unsigned long m_timeout; // IO timeout value
wxList m_states; // stack of states wxList m_states; // stack of states

View File

@@ -499,6 +499,10 @@ public:
Returns @true if an error occurred in the last IO operation. Returns @true if an error occurred in the last IO operation.
Use this function to check for an error condition after one of the Use this function to check for an error condition after one of the
following calls: Discard, Peek, Read, ReadMsg, Unread, Write, WriteMsg. following calls: Discard, Peek, Read, ReadMsg, Unread, Write, WriteMsg.
Notice that this function will return @true even if the other end of a
(connected, i.e. TCP) socket was orderly closed by the peer. Use
IsClosed() to check for this.
*/ */
bool Error() const; bool Error() const;
@@ -567,6 +571,13 @@ public:
*/ */
bool IsConnected() const; bool IsConnected() const;
/**
Return @true if the other end of the socket was closed by the peer.
Notice that Error() will return @true as well when this happens.
*/
bool IsClosed() const;
/** /**
This function waits until the socket is readable. This might mean that This function waits until the socket is readable. This might mean that
queued data is available for reading or, for streamed sockets, that queued data is available for reading or, for streamed sockets, that

View File

@@ -41,8 +41,11 @@ wxSocketOutputStream::~wxSocketOutputStream()
size_t wxSocketOutputStream::OnSysWrite(const void *buffer, size_t size) size_t wxSocketOutputStream::OnSysWrite(const void *buffer, size_t size)
{ {
size_t ret = m_o_socket->Write((const char *)buffer, size).LastCount(); const size_t ret = m_o_socket->Write(buffer, size).LastCount();
m_lasterror = m_o_socket->Error() ? wxSTREAM_WRITE_ERROR : wxSTREAM_NO_ERROR; m_lasterror = m_o_socket->Error()
? m_o_socket->IsClosed() ? wxSTREAM_EOF
: wxSTREAM_WRITE_ERROR
: wxSTREAM_NO_ERROR;
return ret; return ret;
} }
@@ -61,8 +64,11 @@ wxSocketInputStream::~wxSocketInputStream()
size_t wxSocketInputStream::OnSysRead(void *buffer, size_t size) size_t wxSocketInputStream::OnSysRead(void *buffer, size_t size)
{ {
size_t ret = m_i_socket->Read((char *)buffer, size).LastCount(); const size_t ret = m_i_socket->Read(buffer, size).LastCount();
m_lasterror = m_i_socket->Error() ? wxSTREAM_READ_ERROR : wxSTREAM_NO_ERROR; m_lasterror = m_i_socket->Error()
? m_i_socket->IsClosed() ? wxSTREAM_EOF
: wxSTREAM_READ_ERROR
: wxSTREAM_NO_ERROR;
return ret; return ret;
} }

View File

@@ -203,7 +203,8 @@ void wxSocketBase::Init()
m_establishing = m_establishing =
m_reading = m_reading =
m_writing = m_writing =
m_error = false; m_error =
m_closed = false;
m_lcount = 0; m_lcount = 0;
m_timeout = 600; m_timeout = 600;
m_beingDeleted = false; m_beingDeleted = false;
@@ -339,8 +340,10 @@ wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
return *this; return *this;
} }
wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes) wxUint32 wxSocketBase::_Read(void* buffer_, wxUint32 nbytes)
{ {
char *buffer = (char *)buffer_;
int total; int total;
// Try the pushback buffer first // Try the pushback buffer first
@@ -365,35 +368,53 @@ wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
if (m_flags & wxSOCKET_NOWAIT) if (m_flags & wxSOCKET_NOWAIT)
{ {
m_socket->SetNonBlocking(1); m_socket->SetNonBlocking(1);
ret = m_socket->Read((char *)buffer, nbytes); ret = m_socket->Read(buffer, nbytes);
m_socket->SetNonBlocking(0); m_socket->SetNonBlocking(0);
if (ret > 0) if ( ret < 0 )
total += ret; return 0;
}
else
{
bool more = true;
while (more) total += ret;
}
else // blocking socket
{
for ( ;; )
{ {
// dispatch events unless disabled
if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() ) if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
break; break;
ret = m_socket->Read((char *)buffer, nbytes); ret = m_socket->Read(buffer, nbytes);
if ( ret == 0 )
if (ret > 0)
{ {
total += ret; // for connection-oriented (e.g. TCP) sockets we can only read 0
nbytes -= ret; // bytes if the other end has been closed, and for connectionless
buffer = (char *)buffer + ret; // ones (UDP) this flag doesn't make sense anyhow so we can set it to
// true too without doing any harm
m_closed = true;
break;
} }
// If we got here and wxSOCKET_WAITALL is not set, we can leave if ( ret < 0 )
// now. Otherwise, wait until we recv all the data or until there {
// is an error. // this will be always interpreted as error by Read()
// return 0;
more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL)); }
total += ret;
// if wxSOCKET_WAITALL is not set, we can leave now as we did read
// something
if ( !(m_flags & wxSOCKET_WAITALL) )
break;
// otherwise check if read the maximal requested amount of data
nbytes -= ret;
if ( !nbytes )
break;
// we didn't, so continue reading
buffer = (char *)buffer + ret;
} }
} }
@@ -538,8 +559,10 @@ wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
return *this; return *this;
} }
wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes) wxUint32 wxSocketBase::_Write(const void *buffer_, wxUint32 nbytes)
{ {
const char *buffer = (const char *)buffer_;
wxUint32 total = 0; wxUint32 total = 0;
// If the socket is invalid or parameters are ill, return immediately // If the socket is invalid or parameters are ill, return immediately
@@ -556,35 +579,42 @@ wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
if (m_flags & wxSOCKET_NOWAIT) if (m_flags & wxSOCKET_NOWAIT)
{ {
m_socket->SetNonBlocking(1); m_socket->SetNonBlocking(1);
ret = m_socket->Write((const char *)buffer, nbytes); ret = m_socket->Write(buffer, nbytes);
m_socket->SetNonBlocking(0); m_socket->SetNonBlocking(0);
if (ret > 0) if (ret > 0)
total = ret; total = ret;
} }
else else // blocking socket
{ {
bool more = true; for ( ;; )
while (more)
{ {
if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() ) if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
break; break;
ret = m_socket->Write((const char *)buffer, nbytes); ret = m_socket->Write(buffer, nbytes);
if (ret > 0) // see comments for similar logic for ret handling in _Read()
if ( ret == 0 )
{ {
total += ret; m_closed = true;
nbytes -= ret; break;
buffer = (const char *)buffer + ret;
} }
// If we got here and wxSOCKET_WAITALL is not set, we can leave if ( ret < 0 )
// now. Otherwise, wait until we send all the data or until there {
// is an error. return 0;
// }
more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
total += ret;
if ( !(m_flags & wxSOCKET_WAITALL) )
break;
nbytes -= ret;
if ( !nbytes )
break;
buffer = (const char *)buffer + ret;
} }
} }