Non-blocking socket input/output.

This commit is contained in:
Vincent Richard 2005-09-14 22:03:56 +00:00
parent c2a41984af
commit 344d96539d
2 changed files with 51 additions and 22 deletions

View File

@ -33,6 +33,10 @@
#include <string.h> #include <string.h>
#ifdef _POSIX_PRIORITY_SCHEDULING
#include <sched.h>
#endif // _POSIX_PRIORITY_SCHEDULING
namespace vmime { namespace vmime {
namespace platforms { namespace platforms {
@ -201,7 +205,11 @@ vmime::utility::childProcessFactory* posixHandler::getChildProcessFactory() cons
void posixHandler::wait() const void posixHandler::wait() const
{ {
#ifdef _POSIX_PRIORITY_SCHEDULING
::sched_yield();
#else
::sleep(1); ::sleep(1);
#endif // _POSIX_PRIORITY_SCHEDULING
} }

View File

@ -18,6 +18,7 @@
// //
#include "vmime/platforms/posix/posixSocket.hpp" #include "vmime/platforms/posix/posixSocket.hpp"
#include "vmime/platforms/posix/posixHandler.hpp"
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -121,12 +122,19 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port
("Error while connecting socket.", e); ("Error while connecting socket.", e);
} }
} }
::fcntl(m_desc, F_SETFL, ::fcntl(m_desc, F_GETFL) | O_NONBLOCK);
} }
const bool posixSocket::isConnected() const const bool posixSocket::isConnected() const
{ {
return (m_desc != -1); if (m_desc == -1)
return false;
char buff;
return ::recv(m_desc, &buff, 1, MSG_PEEK) != 0;
} }
@ -144,47 +152,60 @@ void posixSocket::disconnect()
void posixSocket::receive(vmime::string& buffer) void posixSocket::receive(vmime::string& buffer)
{ {
::ssize_t ret = ::recv(m_desc, m_buffer, sizeof(m_buffer), 0); const int size = receiveRaw(m_buffer, sizeof(m_buffer));
buffer = vmime::string(m_buffer, size);
if (ret == -1)
{
// Error or no data
return;
}
else if (ret > 0)
{
buffer = vmime::string(m_buffer, ret);
}
} }
const int posixSocket::receiveRaw(char* buffer, const int count) const int posixSocket::receiveRaw(char* buffer, const int count)
{ {
::ssize_t ret = ::recv(m_desc, buffer, count, 0); const int ret = ::recv(m_desc, buffer, count, 0);
if (ret == -1) if (ret < 0)
{ {
// Error or no data if (errno != EAGAIN)
return (0); throwSocketError(errno);
// No data available at this time
return 0;
} }
else else if (ret == 0)
{ {
return (ret); // Host shutdown
throwSocketError(ENOTCONN);
} }
return ret;
} }
void posixSocket::send(const vmime::string& buffer) void posixSocket::send(const vmime::string& buffer)
{ {
if (::send(m_desc, buffer.data(), buffer.length(), 0) == -1) sendRaw(buffer.data(), buffer.length());
throwSocketError(errno);
} }
void posixSocket::sendRaw(const char* buffer, const int count) void posixSocket::sendRaw(const char* buffer, const int count)
{ {
if (::send(m_desc, buffer, count, 0) == -1) int size = count;
while (size > 0)
{
const int ret = ::send(m_desc, buffer, size, 0);
if (ret < 0)
{
if (errno != EAGAIN)
throwSocketError(errno); throwSocketError(errno);
platformDependant::getHandler()->wait();
}
else
{
buffer += ret;
size -= ret;
}
}
} }