thrift0.8.0不支持Win7环境(XP没试过)。要想开启支持,必须修改thrift的源代码。
修改的代码如下
void TServerSocket::listen() {
#ifdef _WIN32
WSADATA wsa_data;
WSAStartup(MAKEWORD(2, 2), &wsa_data);
#endif
int sv[2];
if (-1 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
GlobalOutput.perror("TServerSocket::listen() socketpair() ", errno);
intSock1_ = -1;
intSock2_ = -1;
} else {
intSock1_ = sv[1];
intSock2_ = sv[0];
}
struct addrinfo hints, *res, *res0;
int error;
char port[sizeof("65536") + 1];
std::memset(&hints, 0, sizeof(hints));
#ifdef _WIN32
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;//AI_PASSIVE | AI_ADDRCONFIG;
#else
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
#endif
sprintf(port, "%d", port_);
// Wildcard address
error = getaddrinfo(NULL, port, &hints, &res0);
if (error) {
GlobalOutput.printf("getaddrinfo %d: %s", error, gai_strerror(error));
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not resolve host for server socket.");
}
// Pick the ipv6 address first since ipv4 addresses can be mapped
// into ipv6 space.
for (res = res0; res; res = res->ai_next) {
if (res->ai_family == AF_INET6 || res->ai_next == NULL)
break;
}
if (! path_.empty()) {
#ifdef _WIN32
serverSocket_ = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
#else
serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP);
#endif
} else {
serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
}
if (serverSocket_ == -1) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() socket() ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not create server socket.", errno_copy);
}
// Set reusaddress to prevent 2MSL delay on accept
int one = 1;
if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_REUSEADDR,
cast_sockopt(&one), sizeof(one))) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_REUSEADDR ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_REUSEADDR", errno_copy);
}
// Set TCP buffer sizes
if (tcpSendBuffer_ > 0) {
if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_SNDBUF,
cast_sockopt(&tcpSendBuffer_), sizeof(tcpSendBuffer_))) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_SNDBUF ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_SNDBUF", errno_copy);
}
}
if (tcpRecvBuffer_ > 0) {
if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_RCVBUF,
cast_sockopt(&tcpRecvBuffer_), sizeof(tcpRecvBuffer_))) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_RCVBUF ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_RCVBUF", errno_copy);
}
}
// Defer accept
#ifdef TCP_DEFER_ACCEPT
if (-1 == setsockopt(serverSocket_, SOL_SOCKET, TCP_DEFER_ACCEPT,
&one, sizeof(one))) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_DEFER_ACCEPT ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_DEFER_ACCEPT", errno_copy);
}
#endif // #ifdef TCP_DEFER_ACCEPT
#ifdef IPV6_V6ONLY
if (res->ai_family == AF_INET6 && path_.empty()) {
int zero = 0;
if (-1 == setsockopt(serverSocket_, IPPROTO_IPV6, IPV6_V6ONLY,
cast_sockopt(&zero), sizeof(zero))) {
GlobalOutput.perror("TServerSocket::listen() IPV6_V6ONLY ", errno);
}
}
#endif // #ifdef IPV6_V6ONLY
// Turn linger off, don't want to block on calls to close
struct linger ling = {0, 0};
if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER,
cast_sockopt(&ling), sizeof(ling))) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_LINGER ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_LINGER", errno_copy);
}
// Unix Sockets do not need that
if (path_.empty()) {
// TCP Nodelay, speed over bandwidth
if (-1 == setsockopt(serverSocket_, IPPROTO_TCP, TCP_NODELAY,
cast_sockopt(&one), sizeof(one))) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_NODELAY ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_NODELAY", errno_copy);
}
}
// Set NONBLOCK on the accept socket
int flags = fcntl(serverSocket_, F_GETFL, 0);
if (flags == -1) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() fcntl() F_GETFL ", errno_copy);
throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed", errno_copy);
}
if (-1 == fcntl(serverSocket_, F_SETFL, flags | O_NONBLOCK)) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() fcntl() O_NONBLOCK ", errno_copy);
throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed", errno_copy);
}
// prepare the port information
// 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;
if (! path_.empty()) {
#ifndef _WIN32
// Unix Domain Socket
struct sockaddr_un address;
socklen_t len;
if (path_.length() > sizeof(address.sun_path)) {
int errno_copy = errno;
GlobalOutput.perror("TSocket::listen() Unix Domain socket path too long", errno_copy);
throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path too long");
}
address.sun_family = AF_UNIX;
snprintf(address.sun_path, sizeof(address.sun_path), "%s", path_.c_str());
len = sizeof(address);
do {
if (0 == bind(serverSocket_, (struct sockaddr *) &address, len)) {
break;
}
// use short circuit evaluation here to only sleep if we need to
} while ((retries++ < retryLimit_) && (sleep(retryDelay_) == 0));
} else {
do {
if (0 == bind(serverSocket_, res->ai_addr, res->ai_addrlen)) {
break;
}
// use short circuit evaluation here to only sleep if we need to
} while ((retries++ < retryLimit_) && (sleep(retryDelay_) == 0));
// free addrinfo
freeaddrinfo(res0);
#else
GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on windows", -99);
throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path not supported");
#endif
}
// throw an error if we failed to bind properly
if (retries > retryLimit_) {
char errbuf[1024];
if (! path_.empty()) {
sprintf(errbuf, "TServerSocket::listen() PATH %s", path_.c_str());
}
else {
sprintf(errbuf, "TServerSocket::listen() BIND %d", port_);
}
GlobalOutput(errbuf);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not bind");
}
#ifdef _WIN32
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port_);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
if (0 != ::bind(serverSocket_, (struct sockaddr *)&addr, len))
{
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() bind() ", errno_copy);
}
#endif
// Call listen
if (-1 == ::listen(serverSocket_, acceptBacklog_)) {
int errno_copy = errno;
GlobalOutput.perror("TServerSocket::listen() listen() ", errno_copy);
close();
throw TTransportException(TTransportException::NOT_OPEN, "Could not listen", errno_copy);
}
// The socket is now listening!
}