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:
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user