acceptBacklog_(1024),
sendTimeout_(0),
recvTimeout_(0),
+ retryLimit_(0),
+ retryDelay_(0),
intSock1_(-1),
intSock2_(-1) {}
acceptBacklog_(1024),
sendTimeout_(sendTimeout),
recvTimeout_(recvTimeout),
+ retryLimit_(0),
+ retryDelay_(0),
intSock1_(-1),
intSock2_(-1) {}
recvTimeout_ = recvTimeout;
}
+void TServerSocket::setRetryLimit(int retryLimit) {
+ retryLimit_ = retryLimit;
+}
+
+void TServerSocket::setRetryDelay(int retryDelay) {
+ retryDelay_ = retryDelay;
+}
+
void TServerSocket::listen() {
int sv[2];
if (-1 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed");
}
- // Bind to a port
+ // prepare the port information
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port_);
addr.sin_addr.s_addr = INADDR_ANY;
- if (-1 == bind(serverSocket_, (struct sockaddr *)&addr, sizeof(addr))) {
+
+ // we may want to try to bind more than once, since SO_REUSEADDR doesn't
+ // always seem to work. The client can configure the retry variables.
+ int retries = 0;
+ do {
+ if (0 == bind(serverSocket_, (struct sockaddr *)&addr, sizeof(addr))) {
+ break;
+ }
+
+ // use short circuit evaluation here to only sleep if we need to
+ } while ((retries++ < retryLimit_) && (sleep(retryDelay_) == 0));
+
+ // throw an error if we failed to bind properly
+ if (retries > retryLimit_) {
char errbuf[1024];
sprintf(errbuf, "TServerSocket::listen() BIND %d", port_);
perror(errbuf);
if (recvTimeout_ > 0) {
client->setRecvTimeout(recvTimeout_);
}
-
+
return client;
}