Interprocess communication overviewClasses: wxServer, wxConnection, wxClient wxWidgets has a number of different classes to help with interprocess communication and network programming. This section only discusses one family of classes -- the DDE-like protocol -- but here's a list of other useful classes:
wxWidgets' DDE-like protocol is a high-level protocol based on Windows DDE. There are two implementations of this DDE-like protocol: one using real DDE running on Windows only, and another using TCP/IP (sockets) that runs on most platforms. Since the API and virtually all of the behaviour is the same apart from the names of the classes, you should find it easy to switch between the two implementations. Notice that by including <wx/ipc.h> you may define convenient synonyms for the IPC classes: wxServer for either wxDDEServer or wxTCPServer depending on whether DDE-based or socket-based implementation is used and the same thing for wxClient and wxConnection. By default, the DDE implementation is used under Windows. DDE works within one computer only. If you want to use IPC between different workstations you should define wxUSE_DDE_FOR_IPC as 0 before including this header -- this will force using TCP/IP implementation even under Windows. The following description refers to wx... but remember that the equivalent wxTCP... and wxDDE... classes can be used in much the same way. Three classes are central to the DDE-like API:
Messages between applications are usually identified by three variables: connection object, topic name and item name. A data string is a fourth element of some messages. To create a connection (a conversation in Windows parlance), the client application uses wxClient::MakeConnection to send a message to the server object, with a string service name to identify the server and a topic name to identify the topic for the duration of the connection. Under Unix, the service name may be either an integer port identifier in which case an Internet domain socket will be used for the communications or a valid file name (which shouldn't exist and will be deleted afterwards) in which case a Unix domain socket is created. SECURITY NOTE: Using Internet domain sockets is extremely insecure for IPC as there is absolutely no access control for them, use Unix domain sockets whenever possible! The server then responds and either vetoes the connection or allows it. If allowed, both the server and client objects create wxConnection objects which persist until the connection is closed. The connection object is then used for sending and receiving subsequent messages between client and server - overriding virtual functions in your class derived from wxConnection allows you to handle the DDE messages. To create a working server, the programmer must:
To create a working client, the programmer must:
Data transfer
Data transferThese are the ways that data can be transferred from one application to another. These are methods of wxConnection.
The default data type is wxCF_TEXT (ASCII text), and the default data size is the length of the null-terminated string. Windows-specific data types could also be used on the PC.
ExamplesSee the sample programs server and client in the IPC samples directory. Run the server, then the client. This demonstrates using the Execute, Request, and Poke commands from the client, together with an Advise loop: selecting an item in the server list box causes that item to be highlighted in the client list box.
More DDE detailsA wxClient object initiates the client part of a client-server DDE-like (Dynamic Data Exchange) conversation (available in both Windows and Unix). To create a client which can communicate with a suitable server, you need to derive a class from wxConnection and another from wxClient. The custom wxConnection class will receive communications in a 'conversation' with a server. and the custom wxServer is required so that a user-overridden wxClient::OnMakeConnection member can return a wxConnection of the required class, when a connection is made. For example:
class MyConnection: public wxConnection { public: MyConnection(void)::wxConnection() {} ~MyConnection(void) { } bool OnAdvise(const wxString& topic, const wxString& item, char *data, int size, wxIPCFormat format) { wxMessageBox(topic, data); } }; class MyClient: public wxClient { public: MyClient(void) {} wxConnectionBase *OnMakeConnection(void) { return new MyConnection; } };Here, MyConnection will respond to OnAdvise messages sent by the server by displaying a message box. When the client application starts, it must create an instance of the derived wxClient. In the following, command line arguments are used to pass the host name (the name of the machine the server is running on) and the server name (identifying the server process). Calling wxClient::MakeConnection implicitly creates an instance of MyConnection if the request for a connection is accepted, and the client then requests an Advise loop from the server (an Advise loop is where the server calls the client when data has changed).
wxString server = "4242"; wxString hostName; wxGetHostName(hostName); // Create a new client MyClient *client = new MyClient; connection = (MyConnection *)client->MakeConnection(hostName, server, "IPC TEST"); if (!connection) { wxMessageBox("Failed to make connection to server", "Client Demo Error"); return NULL; } connection->StartAdvise("Item"); |