summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2007-05-23 12:49:48 +0000
committerBenoit Foucher <benoit@zeroc.com>2007-05-23 12:49:48 +0000
commit4f11b3b9bc858d7a5a8741fcb06ca61ce8189d6c (patch)
tree3fa912fd7db2b611fb76a8f7bc9547c39737b024 /cpp/src
parentFixed VS8 compilation error (diff)
downloadice-4f11b3b9bc858d7a5a8741fcb06ca61ce8189d6c.tar.bz2
ice-4f11b3b9bc858d7a5a8741fcb06ca61ce8189d6c.tar.xz
ice-4f11b3b9bc858d7a5a8741fcb06ca61ce8189d6c.zip
Added Ice.TCP.SndSize/Ice.TCP.RcvSize properties, fixed throughput issue on
Win32.
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Ice/Network.cpp197
-rw-r--r--cpp/src/Ice/Network.h9
-rw-r--r--cpp/src/Ice/PropertyNames.cpp4
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/src/Ice/TcpAcceptor.cpp2
-rw-r--r--cpp/src/Ice/TcpConnector.cpp1
-rw-r--r--cpp/src/Ice/TcpTransceiver.cpp20
-rw-r--r--cpp/src/Ice/TcpTransceiver.h2
-rw-r--r--cpp/src/IceSSL/AcceptorI.cpp2
-rw-r--r--cpp/src/IceSSL/ConnectorI.cpp1
-rw-r--r--cpp/src/IceSSL/TransceiverI.cpp17
-rw-r--r--cpp/src/IceSSL/TransceiverI.h2
12 files changed, 138 insertions, 121 deletions
diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp
index 6e907c4bdbe..8e02559e8c6 100644
--- a/cpp/src/Ice/Network.cpp
+++ b/cpp/src/Ice/Network.cpp
@@ -10,6 +10,8 @@
#include <IceUtil/StaticMutex.h>
#include <Ice/Network.h>
#include <Ice/LocalException.h>
+#include <Ice/Properties.h> // For setTcpBufSize
+#include <Ice/LoggerUtil.h> // For setTcpBufSize
#if defined(_WIN32)
# include <winsock2.h>
@@ -1297,10 +1299,66 @@ IceInternal::getLocalHosts()
vector<string> result;
#if defined(_WIN32)
- vector<struct sockaddr_in> addrs = getLocalAddresses();
- for(unsigned int i = 0; i < addrs.size(); ++i)
+ try
{
- result.push_back(inetAddrToString(addrs[i].sin_addr));
+ SOCKET fd = createSocket(false);
+
+ vector<unsigned char> buffer;
+ buffer.resize(1024);
+ unsigned long len = 0;
+ DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0,
+ &buffer[0], static_cast<DWORD>(buffer.size()),
+ &len, 0, 0);
+ if(rs == SOCKET_ERROR)
+ {
+ //
+ // If the buffer wasn't big enough, resize it to the
+ // required length and try again.
+ //
+ if(getSocketErrno() == WSAEFAULT)
+ {
+ buffer.resize(len);
+ rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0,
+ &buffer[0], static_cast<DWORD>(buffer.size()),
+ &len, 0, 0);
+ }
+
+ if(rs == SOCKET_ERROR)
+ {
+ closeSocketNoThrow(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = getSocketErrno();
+ throw ex;
+ }
+ }
+
+ //
+ // Add the local interface addresses.
+ //
+ SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]);
+ for (int i = 0; i < addrs->iAddressCount; ++i)
+ {
+ result.push_back(
+ inetAddrToString(reinterpret_cast<struct sockaddr_in*>(addrs->Address[i].lpSockaddr)->sin_addr));
+ }
+
+ //
+ // Add the loopback interface address.
+ //
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(0);
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ result.push_back(inetAddrToString(addr.sin_addr));
+
+ closeSocket(fd);
+ }
+ catch(const Ice::LocalException&)
+ {
+ //
+ // TODO: Warning?
+ //
}
#elif defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__)
struct ifaddrs* ifap;
@@ -1397,118 +1455,53 @@ IceInternal::getLocalHosts()
return result;
}
-#ifdef _WIN32
-vector<struct sockaddr_in>
-IceInternal::getLocalAddresses()
+void
+IceInternal::setTcpBufSize(SOCKET fd, const Ice::PropertiesPtr& properties, const Ice::LoggerPtr& logger)
{
- vector<struct sockaddr_in> result;
- try
- {
- SOCKET fd = createSocket(false);
-
- vector<unsigned char> buffer;
- buffer.resize(1024);
- unsigned long len = 0;
- DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0,
- &buffer[0], static_cast<DWORD>(buffer.size()),
- &len, 0, 0);
- if(rs == SOCKET_ERROR)
- {
- //
- // If the buffer wasn't big enough, resize it to the
- // required length and try again.
- //
- if(getSocketErrno() == WSAEFAULT)
- {
- buffer.resize(len);
- rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0,
- &buffer[0], static_cast<DWORD>(buffer.size()),
- &len, 0, 0);
- }
+ assert(fd != INVALID_SOCKET);
- if(rs == SOCKET_ERROR)
- {
- closeSocketNoThrow(fd);
- SocketException ex(__FILE__, __LINE__);
- ex.error = getSocketErrno();
- throw ex;
- }
- }
- //
- // Add the local interface addresses.
- //
- SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]);
- for (int i = 0; i < addrs->iAddressCount; ++i)
- {
- result.push_back(*reinterpret_cast<struct sockaddr_in*>(addrs->Address[i].lpSockaddr));
- }
-
- //
- // Add the loopback interface address.
- //
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(0);
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- result.push_back(addr);
+ //
+ // By default, on Windows we use a 128KB buffer size. On Unix
+ // platforms, we use the system defaults.
+ //
+#ifdef _WIN32
+ const int dfltBufSize = 128 * 1024;
+#else
+ const int dfltBufSize = 0;
+#endif
+ Int sizeRequested;
- closeSocket(fd);
- }
- catch(const Ice::LocalException&)
+ sizeRequested = properties->getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize);
+ if(sizeRequested > 0)
{
//
- // TODO: Warning?
+ // Try to set the buffer size. The kernel will silently adjust
+ // the size to an acceptable value. Then read the size back to
+ // get the size that was actually set.
//
- }
- return result;
-}
-
-bool
-IceInternal::isLocalAddress(const struct sockaddr_in& addr)
-{
- struct sockaddr_in addr0 = addr;
- addr0.sin_port = htons(0); // Local interface addresses have the port set to 0.
-
- try
- {
- vector<struct sockaddr_in> localAddrs = getLocalAddresses();
- for(vector<struct sockaddr_in>::const_iterator p = localAddrs.begin(); p != localAddrs.end(); ++p)
+ setRecvBufferSize(fd, sizeRequested);
+ int size = getRecvBufferSize(fd);
+ if(size < sizeRequested) // Warn if the size that was set is less than the requested size.
{
- if(compareAddress(addr0, *p))
- {
- return true;
- }
+ Ice::Warning out(logger);
+ out << "TCP receive buffer size: requested size of " << sizeRequested << " adjusted to " << size;
}
}
- catch(const Ice::LocalException&)
+
+ sizeRequested = properties->getPropertyAsIntWithDefault("Ice.TCP.SndSize", dfltBufSize);
+ if(sizeRequested > 0)
{
//
- // TODO: Warning?
+ // Try to set the buffer size. The kernel will silently adjust
+ // the size to an acceptable value. Then read the size back to
+ // get the size that was actually set.
//
- }
- return false;
-}
-
-bool
-IceInternal::isPeerLocal(SOCKET fd)
-{
- socklen_t remoteLen = static_cast<socklen_t>(sizeof(struct sockaddr_in));
- struct sockaddr_in remoteAddr;
- if(getpeername(fd, reinterpret_cast<struct sockaddr*>(&remoteAddr), &remoteLen) == SOCKET_ERROR)
- {
- if(notConnected())
+ setSendBufferSize(fd, sizeRequested);
+ int size = getSendBufferSize(fd);
+ if(size < sizeRequested) // Warn if the size that was set is less than the requested size.
{
- return false;
- }
- else
- {
- closeSocketNoThrow(fd);
- SocketException ex(__FILE__, __LINE__);
- ex.error = getSocketErrno();
- throw ex;
+ Ice::Warning out(logger);
+ out << "TCP send buffer size: requested size of " << sizeRequested << " adjusted to " << size;
}
}
- return isLocalAddress(remoteAddr);
}
-#endif
diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h
index f03836965c6..2d074c17dc7 100644
--- a/cpp/src/Ice/Network.h
+++ b/cpp/src/Ice/Network.h
@@ -15,6 +15,8 @@
#endif
#include <Ice/Config.h>
+#include <Ice/PropertiesF.h> // For setTcpBufSize
+#include <Ice/LoggerF.h> // For setTcpBufSize
#ifdef _WIN32
# include <winsock2.h>
@@ -109,12 +111,7 @@ ICE_API std::string addrToString(const struct sockaddr_in&);
ICE_API std::vector<std::string> getHosts(const std::string&);
ICE_API std::vector<std::string> getLocalHosts();
-#ifdef _WIN32
-ICE_API std::vector<struct sockaddr_in> getLocalAddresses();
-ICE_API bool isLocalAddress(const struct sockaddr_in&);
-ICE_API bool isPeerLocal(SOCKET);
-#endif
-
+ICE_API void setTcpBufSize(SOCKET, const Ice::PropertiesPtr&, const Ice::LoggerPtr&);
ICE_API int getSocketErrno();
ICE_API std::string inetAddrToString(const struct in_addr&);
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index 0744d7d004e..20b4b620765 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -7,7 +7,7 @@
//
// **********************************************************************
-// Generated by makeprops.py from file `../config/PropertyNames.def', Tue May 15 12:31:29 2007
+// Generated by makeprops.py from file `../config/PropertyNames.def', Wed May 23 14:21:55 2007
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -87,6 +87,8 @@ const char* IceInternal::PropertyNames::IceProps[] =
"Ice.Trace.Slicing",
"Ice.UDP.RcvSize",
"Ice.UDP.SndSize",
+ "Ice.TCP.RcvSize",
+ "Ice.TCP.SndSize",
"Ice.UseEventLog",
"Ice.UseSyslog",
"Ice.Warn.AMICallback",
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index 30edd10e84e..9acdaea97c0 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -7,7 +7,7 @@
//
// **********************************************************************
-// Generated by makeprops.py from file `../config/PropertyNames.def', Tue May 15 12:31:29 2007
+// Generated by makeprops.py from file `../config/PropertyNames.def', Wed May 23 14:21:55 2007
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/src/Ice/TcpAcceptor.cpp b/cpp/src/Ice/TcpAcceptor.cpp
index 193aefe8175..2ffb6fd5a0d 100644
--- a/cpp/src/Ice/TcpAcceptor.cpp
+++ b/cpp/src/Ice/TcpAcceptor.cpp
@@ -64,6 +64,7 @@ IceInternal::TcpAcceptor::accept(int timeout)
{
SOCKET fd = doAccept(_fd, timeout);
setBlock(fd, false);
+ setTcpBufSize(fd, _instance->initializationData().properties, _logger);
if(_traceLevels->network >= 1)
{
@@ -119,6 +120,7 @@ IceInternal::TcpAcceptor::TcpAcceptor(const InstancePtr& instance, const string&
_fd = createSocket(false);
setBlock(_fd, false);
getAddress(host, port, _addr);
+ setTcpBufSize(_fd, _instance->initializationData().properties, _logger);
if(_traceLevels->network >= 2)
{
Trace out(_logger, _traceLevels->networkCat);
diff --git a/cpp/src/Ice/TcpConnector.cpp b/cpp/src/Ice/TcpConnector.cpp
index 935aaa9a84a..4effb9ff4d6 100644
--- a/cpp/src/Ice/TcpConnector.cpp
+++ b/cpp/src/Ice/TcpConnector.cpp
@@ -30,6 +30,7 @@ IceInternal::TcpConnector::connect(int timeout)
SOCKET fd = createSocket(false);
setBlock(fd, false);
+ setTcpBufSize(fd, _instance->initializationData().properties, _logger);
doConnect(fd, _addr, timeout);
if(_traceLevels->network >= 1)
diff --git a/cpp/src/Ice/TcpTransceiver.cpp b/cpp/src/Ice/TcpTransceiver.cpp
index 541843223b7..200778293c6 100644
--- a/cpp/src/Ice/TcpTransceiver.cpp
+++ b/cpp/src/Ice/TcpTransceiver.cpp
@@ -85,9 +85,9 @@ IceInternal::TcpTransceiver::write(Buffer& buf, int timeout)
//
// Limit packet size to avoid performance problems on WIN32
//
- if(_isPeerLocal && packetSize > 64 * 1024)
+ if(packetSize > _maxPacketSize)
{
- packetSize = 64 * 1024;
+ packetSize = _maxPacketSize;
}
#endif
@@ -358,12 +358,22 @@ IceInternal::TcpTransceiver::TcpTransceiver(const InstancePtr& instance, SOCKET
_stats(instance->initializationData().stats),
_fd(fd),
_desc(fdToString(fd))
-#ifdef _WIN32
- , _isPeerLocal(isPeerLocal(fd))
-#endif
{
FD_ZERO(&_rFdSet);
FD_ZERO(&_wFdSet);
+
+#ifdef _WIN32
+ //
+ // On Windows, limiting the buffer size is important to prevent
+ // poor throughput performances when transfering large amount of
+ // data. See Microsoft KB article KB823764.
+ //
+ _maxPacketSize = IceInternal::getSendBufferSize(_fd) / 2;
+ if(_maxPacketSize < 512)
+ {
+ _maxPacketSize = 0;
+ }
+#endif
}
IceInternal::TcpTransceiver::~TcpTransceiver()
diff --git a/cpp/src/Ice/TcpTransceiver.h b/cpp/src/Ice/TcpTransceiver.h
index a6a7abbdb29..fe4f78d1724 100644
--- a/cpp/src/Ice/TcpTransceiver.h
+++ b/cpp/src/Ice/TcpTransceiver.h
@@ -54,7 +54,7 @@ private:
const std::string _desc;
#ifdef _WIN32
- const bool _isPeerLocal;
+ int _maxPacketSize;
#endif
};
diff --git a/cpp/src/IceSSL/AcceptorI.cpp b/cpp/src/IceSSL/AcceptorI.cpp
index 2bd7a3e105c..b2fec924caa 100644
--- a/cpp/src/IceSSL/AcceptorI.cpp
+++ b/cpp/src/IceSSL/AcceptorI.cpp
@@ -77,6 +77,7 @@ IceSSL::AcceptorI::accept(int timeout)
SOCKET fd = IceInternal::doAccept(_fd, timeout);
IceInternal::setBlock(fd, false);
+ IceInternal::setTcpBufSize(fd, _instance->communicator()->getProperties(), _logger);
BIO* bio = BIO_new_socket(static_cast<int>(fd), BIO_CLOSE);
if(!bio)
@@ -155,6 +156,7 @@ IceSSL::AcceptorI::AcceptorI(const InstancePtr& instance, const string& adapterN
_fd = IceInternal::createSocket(false);
IceInternal::setBlock(_fd, false);
IceInternal::getAddress(host, port, _addr);
+ IceInternal::setTcpBufSize(_fd, _instance->communicator()->getProperties(), _logger);
if(_instance->networkTraceLevel() >= 2)
{
Trace out(_logger, _instance->networkTraceCategory());
diff --git a/cpp/src/IceSSL/ConnectorI.cpp b/cpp/src/IceSSL/ConnectorI.cpp
index 8a68c3559c3..ffda1471012 100644
--- a/cpp/src/IceSSL/ConnectorI.cpp
+++ b/cpp/src/IceSSL/ConnectorI.cpp
@@ -41,6 +41,7 @@ IceSSL::ConnectorI::connect(int timeout)
SOCKET fd = IceInternal::createSocket(false);
IceInternal::setBlock(fd, false);
+ IceInternal::setTcpBufSize(fd, _instance->communicator()->getProperties(), _logger);
IceInternal::doConnect(fd, _addr, timeout);
// This static_cast is necessary due to 64bit windows. There SOCKET is a non-int type.
diff --git a/cpp/src/IceSSL/TransceiverI.cpp b/cpp/src/IceSSL/TransceiverI.cpp
index 7f51ac52c76..705f02e2071 100644
--- a/cpp/src/IceSSL/TransceiverI.cpp
+++ b/cpp/src/IceSSL/TransceiverI.cpp
@@ -87,9 +87,9 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf, int timeout)
//
// Limit packet size to avoid performance problems on WIN32
//
- if(_isPeerLocal && packetSize > 64 * 1024)
+ if(packetSize > _maxPacketSize)
{
- packetSize = 64 * 1024;
+ packetSize = _maxPacketSize;
}
#endif
@@ -541,10 +541,19 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, SSL* ssl, SOCKET
_adapterName(adapterName),
_incoming(incoming),
_desc(IceInternal::fdToString(fd))
+{
#ifdef _WIN32
- , _isPeerLocal(IceInternal::isPeerLocal(fd))
+ //
+ // On Windows, limiting the buffer size is important to prevent
+ // poor throughput performances when transfering large amount of
+ // data. See Microsoft KB article KB823764.
+ //
+ _maxPacketSize = IceInternal::getSendBufferSize(_fd) / 2;
+ if(_maxPacketSize < 512)
+ {
+ _maxPacketSize = 0;
+ }
#endif
-{
}
IceSSL::TransceiverI::~TransceiverI()
diff --git a/cpp/src/IceSSL/TransceiverI.h b/cpp/src/IceSSL/TransceiverI.h
index 46daa6d9570..d20915ea5f2 100644
--- a/cpp/src/IceSSL/TransceiverI.h
+++ b/cpp/src/IceSSL/TransceiverI.h
@@ -63,7 +63,7 @@ private:
const std::string _desc;
#ifdef _WIN32
- const bool _isPeerLocal;
+ int _maxPacketSize;
#endif
};
typedef IceUtil::Handle<TransceiverI> TransceiverIPtr;