Asynchronous Thrift Java Client over UNIX Domain Socket - java

I have an application consisting of a Java Thrift Asynchronous client communicating with a Python/Twisted Thrift Asynchronous server over TCP using the loopback interface (localhost).
I want to use a UNIX domain socket instead of a TCP socket for increased throughput, but I cannot find a suitable Asynchronous (Non-blocking) UNIX Domain Socket implementation for Java to use with Thrift.
I had this Python/Twisted TCP Thrift server:
handler = ThriftServiceHandler(am)
processor = ThriftServiceHandler.Processor(handler)
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
reactor.listenTCP(PORT, TTwisted.ThriftServerFactory(processor, pfactory), interface="127.0.0.1")
And I managed to create an Asynchronous UNIX Domain Socket Thrift server with:
handler = ThriftServiceHandler(am)
processor = ThriftServiceHandler.Processor(handler)
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
reactor.listenUNIX("thrift.sock", TTwisted.ThriftServerFactory(processor, pfactory))
Currently I have this Java client:
clientManager = new TAsyncClientManager();
factory = new TBinaryProtocol.Factory();
socket = new TNonblockingSocket("127.0.0.1", thriftConstants.PORT);
client = new ThriftService.AsyncClient(this.factory, this.clientManager, this.socket);
But I am missing how to do the Java Client implementation. I looked at using https://github.com/jnr/jnr-unixsocket and https://github.com/kohlschutter/junixsocket, but I couldn't get them to work with Thrift's Java AsyncClient. Any help would be appreciated.
I am using the latest version of Thrift (0.9.2).

Related

Can I add additional field (metadata) to thrift message?

I have generated client and server.
I need to add one more field to message in client and read it in server.
I think about to decorate TProtocol on client side and TProcessor on server side. E.g.:
// Client:
TTransport transport = new TSocket("localhost", 8888);
transport.open();
TProtocol protocol = new DecoratedProtocol(new TBinaryProtocol(transport));
// Server:
TServerTransport transport = new TServerSocket(8888);
TServer server = new TSimpleServer(new Args(transport).processor(new DecoratedProcessor(...)));
But I'm not sure what to do inside DecoratedProtocol and DecoratedProcessor?
There is a solution to add message meta data called the THeaderProtocol, but AFAIK right now this is only implemented for C++. That could be a starting point to implement the same for Java.
EDIT: I just noticed that fbthrift seems to implement THeaderProtocol for Java already.

Apache Thrift tutorial client stuck when using 2 clients - how to make the server multitask?

I'm executing Apache Thrift tutorial for Java.
When running 2 client processes at the same time, the server doesn't accept the 2nd client. Only after the first client finishes, the second one is accepted by the server.
Can anyone explain what's going on?
How can I make the server accept several connections in several threads?
Can anyone explain what's going on?
You already found it out: The TSimpleServer allows only for one connection at a time. It will be available again when the first client disconnects.
How can I make the server accept several connections in several threads?
Use one of the threading servers, whichever fits your use case best.
TThreadPoolServer
TThreadedSelectorServer
TNonBlockingServer
The half-sync/half-async server
Please note, that some of the servers require the client to use TFramedTransport.
Based on other answers, below is the code to enable executing multiple clients simultaneously.
Server (simple):
CalculatorHandler handler = new CalculatorHandler();
Calculator.Processor processor = new Calculator.Processor(handler);
TNonblockingServerSocket serverTransport = new TNonblockingServerSocket(9090);
THsHaServer.Args args = new THsHaServer.Args(serverTransport);
args.processor(processor);
args.transportFactory(new TFramedTransport.Factory());
TServer server = new THsHaServer(args);
server.serve();
Client:
transport = new TSocket("localhost", 9090);
transport.open();
TProtocol protocol = new TBinaryProtocol(new TFramedTransport(transport));
Calculator.Client client = new Calculator.Client(protocol);
perform(client);

Apache Thrift Python-Java 'Connection Refused'

I've recently tried to connect Python to Java using Thrift.
I've written a server on Python (PyPy). I've also written a reference client which works.
Then I've written a Java client which produces only a 'Connection refused' exception.
What's wrong with this? (Recently I've also found a closed issue featuring this problem https://issues.apache.org/jira/browse/THRIFT-1888)
PS. Used Thrift 0.9 release, PyPy 2.0 beta 2, Java 1.7.0_11
test.thrift
namespace java com.test
namespace python test
service TestPing {
void ping()
}
Python server code
class TestPingHandler:
def ping(self):
pass
handler = TestPingHandler()
processor = TestPing.Processor(handler)
transport = TSocket.TServerSocket(port=9091)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()
server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
print 'Starting the server...'
server.serve()
print 'done.'
Java client code
TTransport transport;
transport = new TSocket("localhost", 9091);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
client = new TestPing.Client(protocol);
client.ping();
Reference Python client code
transport = TSocket.TSocket('localhost', 9091)
transport = TTransport.TBufferedTransport(transport)
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = TestPing.Client(protocol)
transport.open()
client.ping()
transport.close()
I had the same issue.
Replacing "localhost" with the ip fixed it.
The reason was: Python used TCPV6, where Java used TCP.
Python:
transport = TSocket.TServerSocket(host="127.0.0.1", port = 9091)
Java:
transport = new TSocket("127.0.0.1", 9091);
transport = new TSocket("localhost", 9091);
TProtocol protocol = new TBinaryProtocol(transport);
transport.open();
This should work...

Communiation with multiple clients via Sockets

I have a Server Socket and 3-4 android devices as clients. I'm using TCP/IP for communications. Which is the best method. Should I use multiple ports for each client? Or should I use same port. If using same function then how should I identify the communication addressed to different devices?
No, you do not need several ports.
ServerSocket server = new ServerSocket(port);
while (true)
{
Socket socket = server.accept();
// do something with this socket - aka 1 client
new SomeClientClass(socket);
InputStream in = socket.getInputStream();
in.read(byte[]);
OutputStream out = socket.getOutputStream;
// out will only write response to its own client.
// when this new SomeClientClassis created, method returns to this point
// in while loop and waits for the next client
}
You can use one port. The client can send you its id. If it can't you can look at the clients IP address to workout which one it is.
There are thousands of TCP client/server code examples on the web, but I would start with the sample code which comes with the JDK,

WCF TCP client with Java Socket server on custom XML messages

I am trying to build a WCF client for a Java Socket server which talks on a custom XML messages. I have created my own custom binding with MessageEncoder and netTCP transport.
Now what I have seen happen is
on the first call to the server, server accepts the connection. However the server then waits for a specific XML packet. This is built into the method interface from client. WCF does not send the XML packet.
Later WCF reports a timeout exception and the channel is faulted.
Will WCF netTCP transport work only with a WCF TCP Server?
Code:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName = "IUserManager", SessionMode=System.ServiceModel.SessionMode.Required)]
public interface IUserManager
{
[System.ServiceModel.OperationContract]
bool SendMessage(string strMessage);
[System.ServiceModel.OperationContract(IsInitiating = true, IsOneWay=true)]
void SendMessageOneWay(string strMessage);
}
I have created a SendMessageOneWay just to initiate the Socket connection. This did not work as well. As I need to reuse the socket, I have set Session.Required.
Please help
The WCF netTCP transport uses a custom TCP-based protocol; it is not a general purpose raw-TCP socket adapter.
Sounds like you will need to create your own custom transport channel. I created a list of resources on writing WCF channels a while ago (might be a bit out of date, but it should still be useful for getting started)
Yes wcf using .net framing protocol which is not interoperable.
http://blogs.msdn.com/b/drnick/archive/2009/01/19/message-framing-part-1.aspx

Categories

Resources