REQUIREMENT protocol.socket |
Type | NEW |
Priority | HIGH |
Status | CLOSED |
Topic | XmlBlaster supports a bidirectional native communication protocol using exactly one socket connection | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Des cription |
RPC (remote procedure call) based frameworks like CORBA, RMI and XmlRpc require the client to set up a callback server for asynchronous callbacks. This causes problems if the client is behind a firewall or if the client may not establish a listen socket. Reusing a socket for callbacks solves this problem. Further this protocol can be used for simple access from other programming languages like C. Protocol specificationDesign decisions:
This specifies the raw data format, '*' is used to symbolize null terminated strings: msgLen[10] flag[6] requestId methodName secretSessionId lenUnzipped userData checkSum[10] +---------+-------+------ -*----------*----------------*-----------*--------+-----------+ Description:
The userData has the following typical layout. qos key len content +-----*---------*-----*----------+
len (written as a string with a terminating 0) is the length of the content.
The following table lists all allowed methods, with their arguments, return values and exceptions.
NOTE:The raw SOCKET address transferred in the connect QoS markup is of the form socket://host:port for example: socket://127.168.1.2:7607 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example any |
Example of a publish() invocation with qos/key/content " 83**I**17711*publish*oxf6hZs**<qos></qos>*<key oid='hello'/>*11*Hello world" Example of a get() invocation with qos/key " 70**I**17711*get*oxf6hZs**<qos></qos>*<key oid='ooo'></key>*0*" Example of a publish() return with qos " 48**R**17711*publish*oxf6hZs**<qos/>**0*" Example of an empty get() " 34**I**17711*get*oxf6hZs**" Example of a ping() (with an empty qos): " 25**I**11*ping***" Example of an XmlBlasterException as a response on a publish() (a content is not shown): " 84**E**17711*publish*oxf6hZs**QueueOverflow*The destination queue is full*0*" Example of a qos/key/content return value of a get() " 81**R**17711*get***<qos></qos>*<key oid='hello'/>*20*Hello world response" Example of a QoS return value of erase() " 60**R**17711*erase***<qos><state id='OK'/></qos>**0*" Example of publish() with two qos/key/content (split to two lines) " 100**I**17711*publish*oxf6hZs**<qos/>*<key oid='x1'/>*6*Hello1<qos/> *<key oid='x2'/>*6*Hello2" The '*' is used as a symbol for a '\0' character (all zero bits) which terminates strings. The content of a message, here for example 'Hello world' is binary data and has no '\0', it is determined by len. The '"' is just to show the boundary, '"' is not part of the message. You can switch on dumping of such SOCKET messages with following command line argument (all in one line): java -Dcom.sun.management.jmxremote org.xmlBlaster.Main -logging/org.xmlBlaster.util.protocol.RequestReplyExecutor FINEST -logging/org.xmlBlaster.util.protocol.socket.SocketExecutor FINEST -logging/org.xmlBlaster.util.xbformat.XbfParser FINEST |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example Java |
Java command line examplesYou can switch on nice debugging output with these options: java -jar lib/xmlBlaster.jar -dump[socket] true -trace[socket] true Here we start the xmlBlaster server and it will offer its SOCKET service on host myHost.com and on port 7766: java -jar lib/xmlBlaster.jar -plugin/socket/hostname myHost.com -plugin/socket/port 7766 This client tries to find an xmlBlaster server instance at host myHost.com and on port 7766: java HelloWorld3 -protocol SOCKET -dispatch/connection/plugin/socket/hostname myHost.com -dispatch/connection/plugin/socket/port 7766 Here we do the same hard coded in Java: ... String[] args = { "-protocol", "SOCKET", "-dispatch/connection/plugin/socket/hostname", "myHost.com", "-dispatch/connection/plugin/socket/port", "7766", "-dispatch/connection/plugin/socket/localHostname", "myHost.com", "-dispatch/connection/plugin/socket/localPort", "8888" }; glob.init(args); ConnectQos qos = new ConnectQos(glob); ... |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example Java |
Using SSL communicationTo establish a SSL connection you need to set some configuration properties on command line or in xmlBlaster.properties. This works out of the box for JDK 1.4 and above. For JDK 1.3 you need to install the SSL support separately. SSL is available with IBM JDK 1.4 as well, using for example a client running with SUN JDK 1.4 or 1.5 to communicate with a xmlBlaster server running with IBM JDK 1.4 (even if compiled with SUN JDK 1.3) works fine. The first step is to generate a certificate with the keytool program that comes with the SDK. Issue the keytool command with the -genkey option to generate a keypair, the -keystore option to specify the key store file, and the -keyalg options to specify the encryption algorithm, read the SSL tutorial and the SSL reference guide for more details: keytool -genkey -dname "cn=xmlBlaster, ou=server, o=xmlBlaster, c=org" -alias xmlBlaster --keypass testtest -keystore testStore -storepass testtest -keyalg RSA Now you are ready to start the xmlBlaster server with enabled SSL (all in one line): java -jar lib/xmlBlaster.jar -plugin/socket/SSL true -plugin/socket/keyStore testStore -plugin/socket/keyStorePassword testtest and finally we start a client to test it (Note: Under real conditions never pass the 'testStore' file itself to the client, for more details read the next section about certificates): java HelloWorld3 -protocol SOCKET -plugin/socket/SSL true -plugin/socket/trustStore testStore To check the encryption dump the TCP/IP packages for example with tcpdump: tcpdump -i lo -A -vvv dst port 7607 If you encounter problems you can switch on SSL debugging with java -Djavax.net.debug=all ... These are the benefits of the above connection:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example Java |
Using SSL communication with additional client authenticationIn the section before we have explained how to establish a SSL connection between a client and xmlBlaster, in that setup xmlBlaster did not authenticate the clients on SSL layer. Let's add additionally client authentication. The following steps create a client private key and than exchange the clients and servers public key so that both sides know the other side. Create a private key for client joe: keytool -genkey -dname "cn=joe, ou=client, o=xmlBlaster, c=org" -alias joe --keypass testtest -keystore testStore.joe -storepass testtest -keyalg RSAExport joe's certificate: keytool -alias joe -export -keystore testStore.joe -storepass testtest -rfc -file joeTrustStore.Certand import it to the servers trust store named testStore: keytool -import -alias joe -file joeTrustStore.Cert -keystore testStore -storepass testtestCreate a certificate of the xmlBlaster server (the servers private key is in testStore which was created in the example before): keytool -alias xmlBlaster -export -keystore testStore -storepass testtest -rfc -file xmlBlasterTrustStore.Certand import it to joe's trust store: keytool -import -alias xmlBlaster -file xmlBlasterTrustStore.Cert -keystore testStore.joe -storepass testtestOn problems look into the key store file and verify all is correct: keytool -list -v -storepass testtest -keystore testStore.joekeytool -list -v -storepass testtest -keystore testStore keytool -printcert -file xmlBlasterTrustStore.Cert Start the server: java -jar lib/xmlBlaster.jar -plugin/socket/SSL true -plugin/socket/keyStore testStore -plugin/socket/keyStorePassword testtest -plugin/socket/trustStore testStore -plugin/socket/trustStorePassword testtest -plugin/socket/needClientAuth trueand a client to test it: java HelloWorld3 -protocol SOCKET -plugin/socket/SSL true -plugin/socket/keyStore testStore.joe -plugin/socket/keyStorePassword testtest -plugin/socket/findStoreInXmlBlasterSearchPath trueThese are the benefits of the above connection:
Note: With the setting -plugin/socket/findStoreInXmlBlasterSearchPath true it is for example possible to put the testStore.joe in the xmlBlaster.jar file and it is found over the CLASSPATH. Note: To simplify the server setup you should add all server settings to the xmlBlasterPlugins.xml file as described in the next example. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example Java |
Configuring SSL and normal SOCKET communicationIf you want to establish a SSL SOCKET server besides a plain text SOCKET server you need to register two SOCKET protocol drivers each listening on a different port. Here is an example of such entries in xmlBlasterPlugins.xml: <plugin id='SOCKET' className='org.xmlBlaster.protocol.socket.SocketDriver'> <action do='LOAD' onStartupRunlevel='3' sequence='2' onFail='resource.configuration.pluginFailed'/> <action do='STOP' onShutdownRunlevel='2' sequence='5'/> </plugin> <plugin id='socket_ssl' className='org.xmlBlaster.protocol.socket.SocketDriver'> <action do='LOAD' onStartupRunlevel='3' sequence='2' onFail='resource.configuration.pluginFailed'/> <action do='STOP' onShutdownRunlevel='2' sequence='5'/> <attribute id='SSL'>true</attribute> <attribute id='trustStore'>testStore</attribute> <attribute id='trustStorePassword'>testtest</attribute> <attribute id='keyStore'>testStore</attribute> <attribute id='keyStorePassword'>testtest</attribute> <attribute id='needClientAuth'>false</attribute> <attribute id='port'>7609</attribute> <attribute id='startUdpListener'>false</attribute> </plugin>
Now the plain SOCKET is listening on default port 7607 and the SSL SOCKET
listens on port 7609. The 'trustStore' settings are need only when you set up
clustering with SSL SOCKET cluster internal communication -
in this case the xmlBlaster server is a client to another xmlBlaster cluster node
and needs the imported certificate of the remote node in 'testStore'.
# Server side: CbProtocolPlugin[socket_ssl][1.0]=\ org.xmlBlaster.protocol.socket.CallbackSocketDriver,SSL=true # Client side: ClientProtocolPlugin[socket_ssl][1.0]=\ org.xmlBlaster.client.protocol.socket.SocketConnection,SSL=true # Client side: ClientCbServerProtocolPlugin[socket_ssl][1.0]=\ org.xmlBlaster.client.protocol.socket.SocketCallbackImpl,SSL=true Starting the server is simple as all configuration is done in the above xmlBlasterPlugins.xml file (please read the previous example on how to initially generate a keystore): java -jar lib/xmlBlaster.jar Here we start a client using the default plain text SOCKET connection: java HelloWorld3 -protocol SOCKET and here we start another client using the secure SSL SOCKET connection: java HelloWorld3 -protocol socket_ssl -plugin/socket_ssl/port 7609 -plugin/socket_ssl/SSL true -plugin/socket_ssl/trustStore testStore The client side xmlBlaster.properties entries 'socket_ssl' are in fact optional, this would work as well: java HelloWorld3 -protocol SOCKET -plugin/socket/port 7609 -plugin/socket/SSL true -plugin/socket/trustStore testStore Notes
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example Java |
Configuring compressionThe xmlBlaster SOCKET protocol supports compression with zlib and jzlib. Compression support is available for C, C++ and Java clients directly and for ActiveX (C#, VisualBasic .net) and Javascript clients via the Java bridge. You can switch on two compression modes with the property plugin/socket/compress/type. If the server side socket plugin has the option zlib:stream enabled (see xmlBlasterPlugins.xml) it won't accept uncompressed clients. If you have both types of clients you need to register two SOCKET protocol driver in xmlBlasterPlugins.xml. Note that the zlib setting compresses block wise and violates the
described SOCKET protocol format, it adds a prefix to the message format.
A first byte at the beginning, the For a simple usage in this test we set following parameters in xmlBlaster.properties protocol=SOCKET # No compression #plugin/socket/compress/type= # Compress each message separately (available only for Java clients) #plugin/socket/compress/type=zlib # Compress in streaming mode (the preferred way, C, C++, Java ... clients) plugin/socket/compress/type=zlib:stream We start now a server and a client instance, the client publishes 10 messages with identical content consisting of one thousand 'X' characters: java org.xmlBlaster.Main java javaclients.HelloWorldPublish -numPublish 10 -contentSize 1000 If we now restart the client and server for each compression mode and add a socket port forwarder which dumps the transferred bytes we get this result:
For no compression you can see that the first message overhead is 505 bytes (1505 bytes - 1000 payload) because we have delivered the topic QoS on first publish. It than reduces to constantly 356 bytes for each published message. The payload (your message content) is 1000 bytes. The 356 bytes are mostly due to the used publish QoS settings. Compressing each message as a unit with zlib reduces the message size to 276 bytes. The compression header adds overhead for each message. Compressing messages with mode zlib:stream reduces the transferred size drastically to 22 bytes per message. The compression header is not transferred again. Note:This result is a very optimistic case as the message content consisted of one thousand 'X' characters. In your real day messages the compression rate will be less and depends on your payload. Compression of SSL connectionscontentSize=1000
contentSize=10000
Again the results for compression of SSL messages are very promising. Try a C (or C++) clientDownload zlib at http://www.gzip.org/zlib/ and edit build.properties to set the zlib pathes, finally compile it with 'build c'. Now you are ready to try: HelloWorld3 -plugin/socket/compress/type zlib:stream -plugin/socket/port 7607 Compile the C++ examples with 'build cpp' and try: PublishDemo -protocol SOCKET -plugin/socket/compress/type zlib:stream -plugin/socket/port 7607 -numPublish 10 -contentSize 10000 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example Java |
Send xmlBlaster scripts over the socket It is possible to send other formats over the socket connection. The data format described in this requirement is coded in the XbfParser.java class. You can however choose to use the XmlScriptParser.java markup to be send (or any other format which may you code yourself). See the requirement client.script how this markup looks like. It is for example used as the default in the EMAIL protocol plugin. Here is an example how to switch to scripting markup send over the socket: #xmlBlaster.properties (server side) CbProtocolPlugin[socket_script][1.0]=org.xmlBlaster.protocol.socket.CallbackSocketDriver,\ compress/type=,\ isNullTerminated=true,\ parserClass=org.xmlBlaster.util.xbformat.XmlScriptParser #xmlBlasterPlugins.xml <plugin create='true' id='socket_script' className='org.xmlBlaster.protocol.socket.SocketDriver'> <action do='LOAD' onStartupRunlevel='4' sequence='20' onFail='resource.configuration.pluginFailed'/> <action do='STOP' onShutdownRunlevel='3' sequence='50'/> <attribute id='compress/type'></attribute> <attribute id='isNullTerminated'>true</attribute> <attribute id='parserClass'>org.xmlBlaster.util.xbformat.XmlScriptParser</attribute> <attribute id='port'>7601</attribute> </plugin> and on client side: #xmlBlaster.properties (client side) ClientProtocolPlugin[socket_script][1.0]=org.xmlBlaster.client.protocol.socket.SocketConnection,\ compress/type=,\ isNullTerminated=true,\ parserClass=org.xmlBlaster.util.xbformat.XmlScriptParser ClientCbServerProtocolPlugin[socket_script][1.0]=org.xmlBlaster.client.protocol.socket.SocketCallbackImpl,\ compress/type=,\ isNullTerminated=true,\ parserClass=org.xmlBlaster.util.xbformat.XmlScriptParser Please note that you have to pass the To send the script compressed over the wire please use the You can switch on dumping of the send and received messages with the following logging configuration used on command line: -logging/org.xmlBlaster.util.xbformat.XmlScriptParser FINEST -logging/org.xmlBlaster.util.protocol.socket.SocketExecutor FINEST which results in a typical logging output like: 02.07.2006 22:58:45 FINEST 10-main SocketExecutor sendMessage: Sending TCP data [<?xml version='1.0' encoding='UTF-8'?> <publish sessionId='sessionId:127.0.0.2-null-1151873723867' requestId='name:115187001' type='I'> <qos> <subscribable/> <expiration lifeTime='-1' forceDestroy='false'/> <persistent/> <forceUpdate/> <isPublish/> </qos> <key oid='Woodlogging' contentMime='text/xml' contentMimeExtended='1.0' domain='greenwood'> <org.xmlBlaster><demo-2/></org.xmlBlaster> </key> <content type='String'>Hi-2</content> </publish> ] 02.07.2006 22:58:45 FINE 10-main SocketExecutor sendMessage: TCP data is send 02.07.2006 22:58:45 FINEST 11-XmlBlaster.SOCKET XmlScriptParser parse: Got script [<?xml version='1.0' encoding='UTF-8'?> <publish sessionId='sessionId:127.0.0.2-null-1151873723867' requestId='name:115187001' type='R'> <qos> <key oid='Woodlogging'/> <rcvTimestamp nanos='1151873925214000000'/> <isPublish/> </qos> </publish> ] With above configuration a typical command line setting to test the setup is: java org.xmlBlaster.Main -logging/org.xmlBlaster.util.xbformat.XmlScriptParser FINEST -logging/org.xmlBlaster.util.protocol.socket.SocketExecutor FINEST java HelloWorld3 -protocol socket_script -plugin/socket_script/port 7601 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Configure |
Server side configurationNote: If you have additional SOCKET plugins registered, you need to replace socket with the name you gave to your plugin, for example socket_ssl, and the property would be for example plugin/socket_ssl/compress/type=zlib:stream. Note: If you configure a property in xmlBlasterPlugins.xml the scope is
already inside the specific plugin and you need to leave away the prefix plugin/socket and
for example directly write responseTimeout.
Additional client side configurationThe Java socket implementation on client side supports
the same properties as the server (we reuse the same implementation).
You need to add the "dispatch/callback/" or "dispatch/connection/" prefix
to the property key.
NOTE: Configuration parameters are specified on command line (-someValue 17) or in the
xmlBlaster.properties file (someValue=17). See requirement "util.property" for details. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Todo |
Note on UDP datagram usageEach network in the Internet is characterised by a Maximum Transmission Unit (MTU), which defines the largest datagram which can be sent on that network. Whilst the total length of a datagram can (in theory) be up to 64 KB, "real world" MTU limits usually mean datagrams are smaller 1500 bytes in total length. Currently we have configured MAX_PACKET_SIZE = 10*1024 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | protocol | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | client.c.socket | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | client.cpp.socket | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See API | org.xmlBlaster.protocol.util.xbformat.Parser | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See API | org.xmlBlaster.protocol.socket.SocketDriver | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See API | org.xmlBlaster.protocol.socket.SocketUrl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See CODE | socket/XmlBlasterAccessUnparsed.c | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | SSL tutorial | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | SSL reference guide | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | Java compression jzlib | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | C compression zlib | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | xmlBlasterPlugins.xml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | xmlBlaster.properties |
This page is generated from the requirement XML file xmlBlaster/doc/requirements/protocol.socket.xml