how to pass object of a class created inside client to server? - c++

I have a client and a server class in which i am sending message from client to server by making use of TCP sockets.
I have a class created in client.cpp named as Employee consisting of variables such as :
int emp_id;
char *emp_name;
float emp_weight;
My question is as follows:
1) How to send object of the employee class from client side to the server i.e how will i pass employee_object shown as follows to server:
employee_object.emp_id=10;
employee_object *emp_name=new char[30];
employee_object.emp_weight=50.2;
Any help will be of great help.I am doing this to make my self clear how to pass different objects of classes from client to server.

You have two main options: directly write the struct or class to the socket, or "serialize" it.
If you do a direct write, it's quite simple, but it requires you take care that your client and server have the same "width" (32 or 64 bit) and "endianness" (little or big). If you're dealing with regular Intel or AMD desktop or server machines only, this isn't much of an issue.
If you want to "serialize," the sky is the limit. Look up Protocol Buffers, Cap'n'Proto, JSON, etc. There are tons of libraries for this, but Stack Overflow is not the site to figure out which one you should use--you'll have to do some research. Some key considerations are whether the format is human-readable (like JSON) and whether it is fast (like Cap'n'Proto, or the direct method mentioned previously).

Related

Apache Thrift for just processing, not server

I hope I don't have misunderstood the Thrift concept, but what I see from (example) questions like this, this framework is composed by different modular layers that can be enabled or disabled.
I'm mostly interesed in the "IDL part" of Thrift, so that I can create a common interface between my C++ code and an external Javascript application. I would like to call C++ functions using JS, with Binary data transmission, and I've already used the compiler for this.
But both my C++ (the server) and JS (client) application already exchange data using a C++ Webserver with Websockets support, it is not provided by Thrift.
So I was thinking to setup the following items:
In JS (already done):
TWebSocketTransport to send data to my "Websocket server" (with host ws://xxx.xxx.xxx.xxx)
TBinaryProtocol to encapsulate the data (using this JS implementation)
The compiled Thrift JS library with the correspondent C++ functions to call (done with the JS compiler)
In C++ (partial):
TBinaryProtocol to encode/decode the data
A TProcessor with handler to get the data from the client and process it
For now, the client is already able to sent requests to my websocket server, I see receiving them in binary form and I just need Thrift to:
Decode the input
Call the appropriate C++ function
Encode the output
My webserver will send the response to the client. So no "Thrift server" is needed here. I see there is the TProcessor->process() function, I'm trying to use it when I receive the binary data but it needs an in/out TProtocol. No problem here... but in order to create the TBinaryProtocol I also need a TTransport! If no Thrift server is expected... what Transport should I use?
I tried to set TTransport to NULL in TBinaryProtocol constructor, but once I use it it gives nullptr exception.
Code is something like:
Init:
boost::shared_ptr<MySDKServiceHandler> handler(new MySDKServiceHandler());
thriftCommandProcessor = boost::shared_ptr<TProcessor>(new MySDKServiceProcessor(handler));
thriftInputProtocol = boost::shared_ptr<TBinaryProtocol>(new TBinaryProtocol(TTransport???));
thriftOutputProtocol = boost::shared_ptr<TBinaryProtocol>(new TBinaryProtocol(TTransport???));
When data arrives:
this->thriftInputProtocol->writeBinary(input); // exception here
this->thriftCommandProcessor->process(this->thriftInputProtocol, this->thriftOutputProtocol, NULL);
this->thriftOutputProtocol->readBinary(output);
I've managed to do it using the following components:
// create the Processor using my compiled Thrift class (from IDL)
boost::shared_ptr<MySDKServiceHandler> handler(new MySDKServiceHandler());
thriftCommandProcessor = boost::shared_ptr<TProcessor>(new ThriftSDKServiceProcessor(handler));
// Transport is needed, I use the TMemoryBuffer so everything is kept in local memory
boost::shared_ptr<TTransport> transport(new apache::thrift::transport::TMemoryBuffer());
// my client/server data is based on binary protocol. I pass the transport to it
thriftProtocol = boost::shared_ptr<TProtocol>(new TBinaryProtocol(transport, 0, 0, false, false));
/* .... when the message arrives through my webserver */
void parseMessage(const byte* input, const int input_size, byte*& output, int& output_size)
{
// get the transports to write and read Thrift data
boost::shared_ptr<TTransport> iTr = this->thriftProtocol->getInputTransport();
boost::shared_ptr<TTransport> oTr = this->thriftProtocol->getOutputTransport();
// "transmit" my data to Thrift
iTr->write(input, input_size);
iTr->flush();
// make the Thrift work using the Processor
this->thriftCommandProcessor->process(this->thriftProtocol, NULL);
// the output transport (oTr) contains the called procedure result
output = new byte[MAX_SDK_WS_REPLYSIZE];
output_size = oTr->read(output, MAX_SDK_WS_REPLYSIZE);
}
My webserver will send the response to the client. So no "Thrift server" is needed here. I see there is the TProcessor->process() function, I'm trying to use it when I receive the binary data but it needs an in/out TProtocol. No problem here... but in order to create the TBinaryProtocol I also need a TTransport! If no Thrift server is expected... what Transport should I use?
The usual pattern is to store the bits somewhere and use that buffer or data stream as the input, same for the output. For certain languages there is a TStreamTransport available, for C++ the TBufferBase class looks promising to me.

DCMTK Understand the "DIMSE No valid Presentation Context ID" error

I'm currently developing a simple application for querying/retrieving data on a PACS. I use DCMTK for this purpose, and a DCM4CHEE PACS as test server.
My goal is to implement simple C-FIND queries, and a C-MOVE retrieving system (coupled with a custom SCP to actually download the data).
To do so, I've created a CustomSCU class, that inherits the DCMTK DcmSCU class.
I first implemented a C-ECHO message, that worked great.
Then, I tried to implement C-FIND requesting, but I got the error "DIMSE No valid Presentation Context ID" (more on that in the next paragraph) from my application, but no other log from DCM4CHEE. I've then used the command tool findscu (from dcmtk) to see if there was some configuration issue but the tool just worked fine. So in order to implement my C-FIND request, I've read the source of findscu (here) and adapted it in my code (meaning that i'm not using DcmSCU::sendCFindRequest but the class DcmFindSU).
But now, i'm facing the same problem with C-MOVE request. My code is pretty straight-forward :
//transfer syntaxes
OFList<OFString> ts;
ts.push_back(UID_LittleEndianExplicitTransferSyntax);
ts.push_back(UID_BigEndianExplicitTransferSyntax);
ts.push_back(UID_LittleEndianImplicitTransferSyntax);
//sop class
OFString pc = UID_MOVEPatientRootQueryRetrieveInformationModel;
addPresentationContext(pc, ts);
DcmDataset query;
query.putAndInsertOFStringArray(DCM_QueryRetrieveLevel, "PATIENT");
query.putAndInsertOFStringArray(DCM_PatientID, <ThePatientId>);
OFCondition condition = sendMOVERequest(findPresentationContextID(pc, ""), getAETitle(), &query, nullptr);
return condition.good();
I've also tried using UID_MOVEStudyRootQueryRetrieveInformationModel instead of UID_MOVEPatientRootQueryRetrieveInformationModel, with the same result : my application shows the error
DIMSE No valid Presentation Context ID
As I understand, a presentation context is concatenation of one or more transfer syntax and one SOP class. I read that the problem could come from the PACS that won't accept my presentation contexts. To be sure, I used the movescu tool (from DCMTK). It worked, and I saw this in the logs from de server DCM4CHEE :
received AAssociatedRQ
pc-1 : as=<numbers>/Patient Root Q/R InfoModel = FIND
ts=<numbers>/Explicit VR Little Endian
ts=<numbers>/Explicit VR Big Endian
ts=<numbers>/Implicit VR Little Endian
That means that the movescu tool does a find before attempting an actual move ?
Therefore, I changed my application context creation with :
OFList<OFString> ts;
ts.push_back(UID_LittleEndianExplicitTransferSyntax);
ts.push_back(UID_BigEndianExplicitTransferSyntax);
ts.push_back(UID_LittleEndianImplicitTransferSyntax);
OFString pc1 = UID_FINDPatientRootQueryRetrieveInformationModel;
OFString pc = UID_MOVEPatientRootQueryRetrieveInformationModel;
addPresentationContext(pc1, ts);
addPresentationContext(pc, ts);
(also tried study root)
But this didn't do the trick.
The problem seems to lie on the client side, as findPresentationContextID(pc, ""); alwasy return 0, no matter what.
I don't feel like it's possible to adapt the code of the movescu tool, as it appears to be very complex and not adequat for simple retrieve operations.
I don't know what to try. I hope someone can help me understand what's going on. That's the last part of my application, as the storage SCP already works.
Regards
It looks like you are not negotiating the association with the PACS.
After adding the presentation contexts and before sending any command, the SCU must connect to the PACS and negotiate the PresentationContexts with DcmSCU::initNetwork and then DcmSCU::negotiateAssociation.

How can I use Bluez5 DBUS API in C++ to pair and connect new devices?

I am writing a bluetooth driver for Intel Edison. Board software is latest available, and I am developing using the Eclipse based IDE.
Bluez version number in this edison release is 5.37.
I am designing a system which has to meet the following requirements:
Scan for bluetooth devices nearby. [X]
Detect sensor devices based on name and MAC address. [X]
Pair and connect sensor devices automatically. []
Last item is the problem since I can detect sensor devices but I am not able to pair them using the bluez5 interface. So far I have tried to use the D-BUS interface but it is not working since I keep getting the following error message:
Method "FindAdapter" with signature "s" on interface "org.bluez.Manager" doesn't exist
Code is presented here. Please note:
DBusConnection *conn -> DBUS_BUS_SYSTEM
const char *adapter -> "hci0".
Code:
DBusMessage *msg, *reply;
DBusError err;
const char *reply_path;
char *path;
msg = dbus_message_new_method_call("org.bluez", "/","org.bluez.Manager", "FindAdapter");
dbus_message_append_args(msg, DBUS_TYPE_STRING, &adapter,DBUS_TYPE_INVALID);
dbus_error_init(&err);
reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
dbus_message_unref(msg);
Any ideas?
To give you an anwser, Pair and Connect are associated with the device-api.txt. To call these methods you can send dbus messages (like you did in the code presented above) or build a Proxy object with the following parameters (found in the documentation) :
name : "org.bluez"
interface "org.bluez.Device1"
path : "/org/bluez/dev_AA_BB_CC_DD_EE" where AA_BB_CC_DD_EE is your device mac address.
If you choose to build a proxy object, you can call methods like Pair or Connect through the proxy.
Could you explain what you are trying to achieve in the code above ? I understand that you want to find which adapter to use (I see the "FindAdapter" method) however it seems you already knows that your adapter name is "hci0".
I have been working with the DBus API exposed by Bluez recently and I was unfamiliar with the interface "org.bluez.Manager".
After a quick search in the official documentation (https://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc) I was able to find the following commit which specifies that the interface was dropped in 2012 :
https://git.kernel.org/cgit/bluetooth/bluez.git/commit/doc?id=86a7b07c22f3a595ba3c48092359287905bf0878
I also noticed you were using the DBus low-level API, as advised by freedesktop themselves (read at the bottom of the page here : https://dbus.freedesktop.org/doc/api/html/group__DBus.html ), this is very complex API useful to create bindings in other languages. If you can, switch to GLib GDBus for a much simpler API.

Accessing other threads or data from POCO HTTPRequestHandler

I have an C++ application that reads a variety of sensors and then acts on them as required. Currently the sensors run in their own threads and have get/set methods for their values.
I'm trying to integrate a web socket server using POCO libraries to display the state of the sensors.
How do I go about getting the sensor information into the HTTPRequestHandler?
Should I be using the POCO::Application class and defining the sensors & server as subsystems? Is there another approach that I should be taking?
You can derive from HTTPRequestHandler and override handleRequest() and give access to the sensor information by for example storing a reference to your sensor info object as a member of the class derived from HTTPRequestHandler.
class SensorStateRequestHandler : public Poco::Net::HTTPRequestHandler
{
public:
SensorStateRequestHandler(SensorInfo &sensorInfo)
: sensorInfo_(sensorInfo)
{}
virtual void handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response) override
{
// receive request websocket frame
sensorInfo_.get_state(); // must be thread safe
// send response websocket frame with sensor state
}
private:
sensorInfo &sensorInfo_;
};
See how WebEventService in macchina.io is implemented - using Poco::Net::HTTPServer, WebSocket and Poco::NotificationQueue.
The design "in a nutshell" is a pub/sub pattern, client subscribes to notifications and receives them through WebSocket; in-process subscriptions/notifications (using Poco events) are also supported. There is a single short-living thread (HTTP handler) launched at subscription time and the rest of communication is through WebSocket reactor-like functionality, so performance and scalability is reasonably good (although there is room for improvement, depending on target platform).
You may consider using macchina.io itself (Apache license) - it is based on POCO/OSP and targets the type of application you have. WebEvent functionality will be part of Poco::NetEx in 1.7.0 release (sheduled for September this year).

Thrift - different Handler instance for each Socket

Im developing a 'proxy' server in Thrift. My problem is, that each connection incomming to the proxy uses the same instance of the Handler. The client implementation of the proxy is in the Handler, so all the clients communicate throuh the same connection to the end server.
I have : n clients -> n sockets -> 1 handler -> 1 socket -> 1 server
What I want to implement : n clients -> n sockets -> n handlers -> n sockets -> 1 server
Now the problem is that if a client changes a 'local' parameter (something that is defined for each client independently) on the server, other clients will work with the changed environment too.
shared_ptr<CassProxyHandler> handler(new CassProxyHandler(adr_s,port_s,keyspace));
shared_ptr<TProcessor> processor(new CassandraProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TFramedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
Is there a way to implement a server, that creates a new instance of the Handler for each server socket instead of using the same handler?
Thanks for any suggestions or help,
#
I have managed to solve this problem. There was a solution already implemented in Java. I have used the same idea and implemented it in C++.
First thing I did is I created a TProcessorFactory instead of the TTransport class. This handles the TProcessors for each connection. It has a map structure in it, so its' get function returns the corresponding TProcessor for each TTransport. The corresponding (unique) TProcessor for each client.
I had to create a new TServer, so it would accept the newly created parameter TProcessorFactory instead of the TProcessor. In the TServer is also necessary to change a couple function calls. Your getProcessor function will no longer return a TProcessor but a TProcessorFactory (so change return type and rename).
The last thing you have to do is implement a server that allows instantiation, a derive class of TServer. I suggest using the TNonblockingServer (bit harder to implement the change) or the TThreadPoolServer. You have to change a couple function calls. Use a get function on the TProcessorFactory with a TTransport parameter to get a TProcessor where needed. The TTransport parameter is unique for each thread, each client connection is handled by one thread.
Also make sure you delete the old TProcessors, because thrift reuses (at least with the TNonblockingServer) the TTransport, so if you do not delete them and a client connects, he will probably get an inactive previous session and you probably don't want it. If you use shared pointers, just remove them from the map structure, when the client disconnects, and if there are no longer needed by thrift, they will be destructed.
I hope this helps to anyone, who encounters the same problem I did. If you don't know the inner structure of thrift, here a good guide : http://diwakergupta.github.com/thrift-missing-guide/
I hope the Thrift developers are going to implement something similar, but more sophisticated and abstract solution in the near future.
#
I know this is an old thread, but in case it's ever of use to anyone - I have contributed a change to the C# implementation of Thrift to solve this problem...
https://issues.apache.org/jira/browse/THRIFT-3397
In addition to the old method of passing a TProcessor as the first argument to the threaded servers, one can now set up something like
new ThreadPoolServer(processorFactory,serverTransport,
transportFactory,protocolFactory);
Where 'processorFactory' is a TProcessorFactory.
I've created TPrototypeProcessorFactory<TProcessor,Handler>(object[] handlerArgs) which would be set up like so:
TProcessorFactory processorFactory =
new TPrototypeProcessorFactory<ThriftGenerated.Processor, MyHandlerClass>();
The 'MyHandlerClass' implements your ThriftGenerated.Iface. Optionally, if this class takes arguments, they can be added as an array of objects to the processor factory.
Internally - For each new client connection, this processor factory will:
Create a new instance of 'MyHandlerClass' using any arguments
supplied (using Activator.CreateInstance)
If 'MyHandlerClass' implements 'TControllingHandler' it will set its
'server' property to the parent TServer (e.g. to allow control of
the TServer using a thift client)
Return a new instance of ThriftGenerated.Processor(handler)
Therefore for C# you get n clients -> n sockets -> n handlers -> n sockets -> 1 server
I hope this becomes useful to other people - it's certainly solved a problem for me.
Instead of making your proxy server talk thrift, you could just make it a generic TCP proxy that opens a new TCP connection for each incoming connection.