(我认为)Thrift服务器只在监听ipv6



我是Apache Thrift的新手,曾在这里玩过Apache提供的玩具Delphi客户端服务器示例:https://thrift.apache.org/tutorial/delphi

我们对名称以及端口和IP的设置方式进行了一些小的更改,但在其他方面基本相同。

服务器中,我们有以下代码:

PORT := StrToInt(ParamStr(1));
handler   := TPhraseGeneratorHandler.Create;
processor := TPhraseGenerator.TProcessorImpl.Create( handler);
transport := TServerSocketImpl.Create( PORT);
server    := TSimpleServer.Create( processor, transport);
WriteLn( 'Starting the server on port ' + PORT.ToString + '...');
server.Serve();

客户端中,我们有以下代码:

var transport     : ITransport;
protocol      : IProtocol;
client        : TPhraseGenerator.Iface;
phraseRequest : IPhraseRequest;
// Let the user pass in the parameters for host and port
HOST : String;
PORT : Integer;
begin
try
// Open a connection to the server using the host and port supplied by the user
HOST := ParamStr(1);
PORT := StrToInt(ParamStr(2));
WriteLn('Openning a connection to the server: ' + HOST + ' on port: ' + PORT.ToString);
transport := TSocketImpl.Create( HOST, PORT, 10000); // specifically add a timeout as our test server deliberately goes to sleep for 5000ms
protocol  := TBinaryProtocolImpl.Create( transport);
client    := TPhraseGenerator.TClient.Create( protocol);
transport.Open;

如果我们在同一台机器上打开客户端和服务器并使用"localhost",我们可以让它们进行通信。

但是,如果我们在不同的机器上打开它们并指定服务器的ipv4地址,我们就不能。

使用netstat,我们得到以下内容:

D:Temp>netstat -ano | findstr 9090
TCP    [::]:9090              [::]:0                 LISTENING       15368

我认为这表明服务器只在侦听ipv6。

Q: 我说得对吗?如果是这样,我们如何让它在ipv4上监听?

我认为你是100%正确的。

CreateSocket():的相关章节

// Pick the ipv6 address first since ipv4 addresses can be mapped
// into ipv6 space.
Res := Result.Res;
while Assigned(Res) do begin
if (Res^.ai_family = AF_INET6) or (not Assigned(Res^.ai_next)) then
Break;
Res := Res^.ai_next;
end;
FSocket := Winapi.Winsock2.socket(Res^.ai_family, Res^.ai_socktype, Res^.ai_protocol);

UPDATE我们已经找到了如何编辑Delphi Thrift代码以允许ipv4。在这里发帖,以防对其他人有帮助。

相关程序是过程TServerSocket。倾听在文件Thrift中。套接字.pas.

procedure TServerSocket.Listen;

var
TempIntReader,
TempIntWriter: Winapi.Winsock2.TSocket;
One: Cardinal;
ErrnoCopy: Integer;
Ling: TLinger;
Retries: Integer;
AddrInfo: IGetAddrInfoWrapper;
SA: TSockAddrStorage;
Len: Integer;
// ### ADD THIS ###
Zero: Cardinal;
// ### END ADD ###

// Set SO_EXCLUSIVEADDRUSE to prevent 2MSL delay on accept
One := 1;
setsockopt(Socket, SOL_SOCKET, Integer(SO_EXCLUSIVEADDRUSE), @one, SizeOf(One));
// ignore errors coming out of this setsockopt on Windows.  This is because
// SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't
// want to force servers to be an admin.
// ### ADD THIS ###
// set IPV6_V6ONLY=0 so that the server uses dualstack sockets
// i.e., we will get both IPv6 and IPv4-mapped IPv6 connections on the same socket
// (ignore errors)
Zero := 0;
setsockopt(Socket, IPPROTO_IPV6, {IPV6_V6ONLY}27, @Zero, SizeOf(Zero));
// ### END ADD ###
// Set TCP buffer sizes
if FTcpSendBuffer > 0 then begin
if setsockopt(Socket, SOL_SOCKET, SO_SNDBUF, @FTcpSendBuffer, SizeOf(FTcpSendBuffer)) = SOCKET_ERROR then begin
ErrnoCopy := WSAGetLastError;
LogDelegate(Format('TServerSocket.Listen() setsockopt() SO_SNDBUF %s', [SysErrorMessage(ErrnoCopy)]));
raise TTransportExceptionNotOpen.Create(Format('Could not set SO_SNDBUF: %s', [SysErrorMessage(ErrnoCopy)]));
end;
end;

最新更新