If I have a pre-existing open file descriptor, referring to an already bound and listening socket, how can I use it to initialize a thrift server object (the non-blocking server preferably) and start accepting RPC requests? The various ThriftSocket objects I've seen only accept address/port (or just port) arguments to create a socket themselves.
For the client side, you have a constructor to construct a socket from a file descriptor:
/**
* Constructor to create socket from file descriptor.
*/
TSocket(THRIFT_SOCKET socket, std::shared_ptr<TConfiguration> config = nullptr);
On Unix system, you can find out that THRIFT_SOCKET is an int, just feed your descriptor here!
Unfortunately, this is not the case for the server side. Inheriting TServerSocket won't solve your issue because the internal socket member is private.
However, the thrift servers all take a TServerTransport as argument. Thus, the idea is to inherit TServerTransport to create a custom TServerSocket. The original TServerSocket can be of help here.
But, the fact they did not add the possibility for this feature might mean it is not safe to do so. You'll have no other choice that inspecting TServerSocket.cpp to check the internal implementation.
Related
I would like to send a UDP datagram from a specified port number WITHOUT binding (ex. when the port is already bound to another socket that I have no control over).
While I do appreciate the OS trying to keep everything nice and clean, and I cherish the bind() functionality, the question is as it is.
How to accomplish this with WSASendTo() or WSASendMsg()?
WSASendTo() will use whichever source IP/Port the socket is currently bound to. If the socket is not bound, WSASendTo() will perform an implicit binding first.
WSASendMsg() can use the IN_PKTINFO/IN6_PKTINFO structs to specify a source IP and source interface, but AFAIK the only way to specify a source port is through bind().
The Boost ASIO library provides a port() get/set method for a socket local_endpoint, but when I try to switch to a different port while the work queue is running, calling socket.local_endpoint().port(1234) call does not change the port. Does anyone have experience with this?
Based on an option received over TFTP, I need to switch the port over which the server and client are communicating.
To answer why
socket.local_endpoint().port(1234) call does not change the port.
as far as I know, the basic_socket class *_endpoint() implementations return a copy of endpoint_type object, not a reference, so the change you are trying to make, won't affect the socket object.
SOCKET sock = generate_socket("fileWizard");
notifier = new QSocketNotifier(sock, QSocketNotifier::Read, this);
connect(notifier, SIGNAL(activate(int)), this, some_slot(int));
The SOCKET is a win32 SOCKET, the function of "generate_socket" is creating a socket connect to a local exe which called "fileWizard"(don't know the implementation details of the function generate_socket).
With Qt, we always generate the socket and connect the signal and slot, but can't find a similar example in asio.
Do not familiar to socket and asio yet, please tell me what information you need. Thanks
Edit :
The purposes of the codes are monitoring the SOCKET, if there are any change of it, it will call the call back.
Similar to the example of asio(Daytime.3 - An asynchronous TCP daytime server)
The part which make me confuse is
1 : How could I transform the SOCKET to one of the boost::asio socket?
2 : How could I monitor the "change"(anything can read) of the socket(our seniors called it file descriptor)?By read_async?
Boost.Asio sockets support being created on top of an existing native socket through an overloaded constructor. For example, this constructor could be used to build a basic_stream_socket on top of an existing native socket, such as a Windows SOCKET.
While Boost.Asio does not provide the direct equivalent of Qt's QSocketNotifier class, Boost.Asio does supports reactor-style operations by using null_buffers(). Both approaches allow the application to be notified when an event occurs, such as when data is ready to be read from a file descriptor. This event notification capability allows for each event loop to integrate with other event loops or third-party libraries. For a complete example that uses null_buffers(), see the official Boost.Asio non-blocking example.
So I wonder - is it possible to pass accepted TCP connection (on Windows or Unix like OS) from one process to another? Here the point is to pass connection - not data in a way a proxy app would.
In Unix, a TCP connection is represented as a socket file descriptor. When you fork a process, the file descriptors are inherited by the child process, including TCP sockets. (Though they may be closed on exec if given the FD_CLOEXEC flag with fcntl.)
It's also possible to transfer file descriptors between unrelated processes using a local (Unix) domain socket; see this question.
I'm not sure about Windows.
On Windows, use WSADuplicateSocket, pass the filled in WSAPROTOCOL_INFO to the other process, use WSPSocket to recreate a socket.
On unix-like OS'es this is possible using the sendmsg() system call. libancillary abstracts this for you.
Hi I am working on an assignment writing multi threaded client server.
So far I have done is open a socket in a port and forked two thread for listening and writing to client. But I need to connect two type of clients to the server and service them differently. My question is what would be my best approach?
I am handling connection in a class which has a infinite loop to accept connection. When ever a connection is accepted, the class create two thread to read and write to client? Now if I wnat to handle another client of different type, what should we do?
Do I need to open another port? or is it possible to service through same port? May be if it is possible to identify the type of client in the socket than I can handle messages differently.
Or do you suggest like this?
Fork two thread for two type of client and monitor inbound connection in each thread in different port.
when a connection accepted each thread spawn another two thread for listening and writing.
please make a suggestion.
Perhaps you'll get a better answer from a Unix user, but I'll provide what I know.
Your server needs a thread that opens a 'listening' socket that waits for incoming connections. This thread can be the main thread for simplicity, but can be an alternate thread if you are concerned about UI interaction, for example (in Windows, this would be a concern, not sure about Unix). It sounds like you are at least this far.
When the 'listening' socket accepts a connection, you get a 'connected' socket that is connected to the 'client' socket. You would pass this 'connected' socket to a new thread that manages the reading from and writing to the 'connected' socket. Thus, one change I would suggest is managing the 'connected' socket in a single thread, not two separate threads (one for reading, one for writing) as you have done. Reading and writing against the same socket can be accomplished using the select() system call, as shown here.
When a new client connects, your 'listening' socket will provide a new 'connected' socket, which you will hand off to another thread. At this point, you have two threads - one that is managing the first connection and one that is managing the second connection. As far as the sockets are concerned, there is no distinction between the clients. You simply have two open connections, one to each of your two clients.
At this point, the question becomes what does it mean to "service them differently". If the clients are expected to interact with the server in unique ways, then this has to be determined somehow. The interactions could be determined based on the 'client' socket's IP address, which you can query, but this seems arbitrary and is subject to network changes. It could also be based on the initial block of data received from the 'client' socket which indicates the type of interaction required. In this case, the thread that is managing the 'connected' socket could read the socket for the expected type of interaction and then hand the socket off to a class object that manages that interaction type.
I hope this helps.
You can handle the read-write on a single client connection in one thread. The simplest solution based on multiple-threads will be this:
// C++ like pseudo-code
while (server_running)
{
client = server.accept();
ClientHandlingThread* cth = CreateNewClientHandlingThread(client);
cth->start();
}
class ClientHandlingThread
{
void start()
{
std::string header = client->read_protocol_header();
// We get a specific implementation of the ProtocolHandler abstract class
// from a factory, which create objects by inspecting some protocol header info.
ProtocolHandler* handler = ProtocolHandlerFactory.create(header);
if (handler)
handler->read_write(client);
else
log("unknown protocol")
}
};
To scale better, you can use a thread pool, instead of spawning a new thread for each client. There are many free thread pool implementations for C++.
while (server_running)
{
client = server.accept();
thread_pool->submit(client);
cth->start();
}
The server could be improved further by using some framework that implements the reactor pattern. They use select or poll functions under the hood. You can use these functions directly. But for a production system it is better to use an existing reactor framework. ACE is one of the most widely known C++ toolkits for developing highly scalable concurrent applications.
Different protocols are generally serviced on different ports. However, you could service both types of clients over the same port by negotiating the protocol to be used. This can be as simple as the client sending either HELO or EHLO to request one or another kind of service.