REQUIREMENT client.c.socket |
Type | NEW |
Priority | HIGH |
Status | CLOSED |
Topic | XmlBlaster provides a client library written in ANSI C | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Des cription |
For C client applications you can use the header XmlBlasterAccessUnparsed.h which provides access to xmlBlaster in an easy way. Features
Functionality All invocations to xmlBlaster are done by invoking function pointers on struct XmlBlasterAccessUnparsed.
Memory footprint On Linux the 'hello world' client executable has a very little footprint, on Windows you need to add the pthreadVC2.lib size of ~ 29 kBytes: 1. Complete synchronous access (without callback and single threaded): XmlBlasterConnectionUnparsedMain: 30 kBytes libc.so.6 => /lib/libc.so.6 (0x4002b000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) 2. Complete client connection and multi threaded callback server: XmlBlasterAccessUnparsedMain: 50 kBytes libpthread.so.0 => /lib/libpthread.so.0 (0x4002b000) libc.so.6 => /lib/libc.so.6 (0x4007b000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) 3. Size of the C client shared library: xmlBlaster/lib/libxmlBlasterClientC.so: 48 kBytes 4. Size of a multi threaded C client (using the above shared library) LogRedirect: 6,3 kBytes libxmlBlasterClientC.so => /opt/xmlBlaster/lib/libxmlBlasterClientC.so (0x40016000) libdl.so.2 => /lib/libdl.so.2 (0x40037000) libpthread.so.0 => /lib/libpthread.so.0 (0x4003a000) libc.so.6 => /lib/libc.so.6 (0x4008a000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) Compilation with ant You can try the ant based compilation, our build.xml supports Linux GNU gcc, Linux Intel icc, Solaris CC and Windows VC++: cd xmlBlaster build c-lib (UNIX gcc) build -Duse-gcc=1 c-lib (Mac OSX with gcc) build -Duse-icc=1 c-lib (UNIX Intel icc compiler) build -Duse-CC=1 c-lib (Solaris CC) build -Duse-msvc=1 c-lib (Windows Visual C++) This creates a shared C library xmlBlaster/lib/libxmlBlasterClientC.so on Linux or xmlBlaster/lib/xmlBlasterClientC.dll on Windows. You can link your C or C++ client code with this library. You can set your preferred compiler in the file xmlBlaster/build.properties to avoid setting it on command line always again: use-msvc = 1 To compile the C client library and the demos in xmlBlaster/demo/c/socket invoke (please use the above compiler names if necessary): cd xmlBlaster build c Currently debugging support in the executable is switched on as default, to switch it off try (the -verbose option is to dump the compilation command line only): build -Dc.debug=false -verbose c You can force using the INTEL C++ compiler by setting use-icc to true: build -Duse-icc=true c Compilation manually Here are some complete examples how to compile a simple C client 'manually': cd xmlBlaster/src/c Linux C: (for Mac OSX add '-D__MacOSX__') gcc -Wall -g -I. -UXB_USE_PTHREADS -o HelloWorld HelloWorld.c util/helper.c util/msgUtil.c util/Properties.c socket/xmlBlasterSocket.c socket/XmlBlasterConnectionUnparsed.c socket/xmlBlasterZlib.c Linux C++: g++ -Wall -g -DXMLBLASTER_C_COMPILE_AS_CPP -I. -o HelloWorld HelloWorld.c util/*.c socket/XmlBlasterConnectionUnparsed.c socket/xmlBlasterSocket.c socket/xmlBlasterZlib.c Windows: cl -D_WINDOWS -DDLL_IGNORE -DXB_NO_PTHREADS -I. HelloWorld.c util\*.c socket\XmlBlasterConnectionUnparsed.c socket\xmlBlasterSocket.c socket\xmlBlasterZlib.c ws2_32.lib Solaris: cc -Xc -g -I. -o HelloWorld HelloWorld.c util/*.c socket/XmlBlasterConnectionUnparsed.c socket/xmlBlasterSocket.c -lsocket -lnsl In the first example we undef XB_USE_PTHREADS to have no thread ID in the logging output, this switch is optional. In the second example we use the C++ compiler instead of the C compiler and force with XMLBLASTER_C_COMPILE_AS_CPP the code to not include extern "C" { ... } constructs, this way we get a pure C++ binary instead of an extern C module. This switch is optional as well. To compile a multi threaded client with synchronous access and asynchronous callbacks: cd xmlBlaster/src/c/socket Linux C: gcc -DXmlBlasterAccessUnparsedMain -Wall -pedantic -g -D_REENTRANT -I.. -o XmlBlasterAccessUnparsedMain XmlBlasterAccessUnparsed.c ../util/*.c xmlBlasterSocket.c XmlBlasterConnectionUnparsed.c CallbackServerUnparsed.c -lpthread Windows: cd xmlBlaster\src\c\socket cl /MT /W4 -DDLL_IGNORE -DXmlBlasterAccessUnparsedMain -D_WINDOWS -I.. -I../pthreads /FeXmlBlasterAccessUnparsedMain.exe XmlBlasterAccessUnparsed.c ..\util\*.c xmlBlasterSocket.c XmlBlasterConnectionUnparsed.c CallbackServerUnparsed.c xmlBlasterZlib.c ws2_32.lib pthreadVC2.lib Windows (including zlib compression): cl /MT /W4 -DDLL_IGNORE -DXmlBlasterAccessUnparsedMain -D_WINDOWS /DXMLBLASTER_ZLIB=1 \ -I.. -I../pthreads /FeXmlBlasterAccessUnparsedMain.exe \ XmlBlasterAccessUnparsed.c ..\util\*.c *.c ws2_32.lib pthreadVC2.lib \zlib121\lib\zdll.lib Solaris: cc -DXmlBlasterAccessUnparsedMain -v -Xc -g -D_REENTRANT -I.. -o XmlBlasterAccessUnparsedMain XmlBlasterAccessUnparsed.c ../util/*.c xmlBlasterSocket.c XmlBlasterConnectionUnparsed.c CallbackServerUnparsed.c -lpthread -lsocket -lnsl Compilation hints are in the source files xmlBlaster/src/c/XmlBlasterConnectionUnparsedMain.c (for synchronous access) xmlBlaster/src/c/socket/XmlBlasterAccessUnparsed.c (for complete multi threaded access including callbacks). Implementation detail The C library consists of 3 independent modules which are XmlBlasterConnectionUnparsed for synchronous access, CallbackServerUnparsed for the client callbacks and XmlBlasterAccessUnparsed which reuses the first two modules and combines them with multi threading to gain complete xmlBlaster functionality. The following sequence diagram shows a use case of a get() invocation, the threads are synchronized using the worker/boss paradigm with the wait/signal approach of pthreads.
A demo using XmlRpc is available as well (see xmlBlaster/demo/c/xmlrpc/README). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example C |
Example for a Windows XP setup Here is an example how to setup the development environment for free on Windows, using our ant build to compile. Compilation steps on a Windows (XP,2003) platform (using free microsoft tools only):
Steps to run the executable:
If you want to use compressed communication, please download Note for C++: You need to download the xerces XML parser |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example C |
Single threaded example This example shows a single threaded synchronous access: 1 /*---------------------------------------------------------------------------- 2 Name: HelloWorld.c 3 Project: xmlBlaster.org 4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file 5 Comment: HelloWorld connects with raw socket to xmlBlaster 6 Author: "Marcel Ruff" <xmlBlaster@marcelruff.info> 7 Compile: 8 Linux C: gcc -Wall -g -D_REENTRANT -I. -o HelloWorld HelloWorld.c util/msgUtil.c 9 util/Properties.c socket/xmlBlasterSocket.c socket/XmlBlasterConnectionUnparsed.c 10 Linux C++: g++ -Wall -g -D_REENTRANT -I. -o HelloWorld HelloWorld.c util/msgUtil.c 11 util/Properties.c socket/xmlBlasterSocket.c socket/XmlBlasterConnectionUnparsed.c 12 -DXMLBLASTER_C_COMPILE_AS_CPP 13 Win: cl /MT /W3 /Wp64 -D_WINDOWS -I. HelloWorld.c util\*.c socket\*.c ws2_32.lib 14 Sun: cc -g -D_REENTRANT -I. -o HelloWorld HelloWorld.c util/msgUtil.c 15 util/Properties.c socket/xmlBlasterSocket.c 16 socket/XmlBlasterConnectionUnparsed.c -lsocket -lnsl 17 18 Linux with shared lib: 19 gcc -o HelloWorld HelloWorld.c -L../../lib -lxmlBlasterClientC -I. 20 -Wl,-rpath=../../lib -lpthread 21 Date: 05/2003 22 -----------------------------------------------------------------------------*/ 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <XmlBlasterConnectionUnparsed.h> 27 28 /** 29 * Access the free memory in the server. 30 */ 31 int main(int argc, char** argv) 32 { 33 MsgUnitArr *msgUnitArr; 34 XmlBlasterException exception; 35 char *connectQos, *response; 36 37 XmlBlasterConnectionUnparsed *xb = getXmlBlasterConnectionUnparsed(argc, argv); 38 39 connectQos = "<qos>" 40 " <securityService type='htpasswd' version='1.0'>" 41 " <user>fritz</user>" 42 " <passwd>secret</passwd>" 43 " </securityService>" 44 "</qos>"; 45 response = xb->connect(xb, connectQos, &exception); 46 xmlBlasterFree(response); 47 if (*exception.errorCode != '\0') { 48 printf("[client] Caught exception during connect, errorCode=%s, message=%s", 49 exception.errorCode, exception.message); 50 freeXmlBlasterConnectionUnparsed(xb); 51 exit(1); 52 } 53 54 printf("[HelloWorld] Connected to xmlBlaster, invoking now get() ...\n"); 55 56 msgUnitArr = xb->get(xb, "<key oid='__cmd:?freeMem'/>", 0, &exception); 57 if (*exception.errorCode != '\0') { 58 printf("[HelloWorld] Caught exception in get errorCode=%s, message=%s", 59 exception.errorCode, exception.message); 60 freeXmlBlasterConnectionUnparsed(xb); 61 exit(1); 62 } 63 if (msgUnitArr != (MsgUnitArr *)0 && msgUnitArr->len > 0) { 64 char *contentStr = strFromBlobAlloc(msgUnitArr->msgUnitArr[0].content, 65 msgUnitArr->msgUnitArr[0].contentLen); 66 printf("[HelloWorld] xmlBlaster has %s bytes of free memory\n", contentStr); 67 xmlBlasterFree(contentStr); 68 } 69 freeMsgUnitArr(msgUnitArr); 70 71 (void)xb->disconnect(xb, 0, &exception); 72 73 freeXmlBlasterConnectionUnparsed(xb); 74 printf("[HelloWorld] Good bye.\n"); 75 return 0; 76 } We include the header XmlBlasterConnectionUnparsed.h on line 26 for synchronous access. This header contains a struct with function pointers on all functions necessary to communicate with xmlBlaster. On line 37 we create a client connection instance (one instance of the above struct), which allows us to connect to xmlBaster and work with the server. If we need multiple connections we just call getXmlBlasterConnectionUnparsed(argc, argv) multiple times which returns totally independent connection handlers which may be used from different threads if desired. After every server invocation (e.g. line 47) we need to check the exception struct. If the errorCode member is filled an exception occurred. The exception source may be from the remote server or from the C library itself. If we are done with our work we need to free all resources (line 73). This assures we have no memory leak even on a C client running 365 days a year without interruption. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example C |
Multi threaded example Here is an example showing multi threaded access with asynchronous callbacks: 1 /*---------------------------------------------------------------------------- 2 Name: xmlBlaster/demo/c/socket/HelloWorld3.c 3 Project: xmlBlaster.org 4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file 5 Comment: Example for all remote method invocations. 6 Author: "Marcel Ruff" <xmlBlaster@marcelruff.info> 7 Compile: cd xmlBlaster; build c 8 (Win: copy xmlBlaster\src\c\socket\pthreadVC2.dll to your PATH) 9 Invoke: HelloWorld3 -help 10 See: http://www.xmlblaster.org/xmlBlaster/doc/requirements/protocol.socket.html 11 -----------------------------------------------------------------------------*/ 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <XmlBlasterAccessUnparsed.h> 16 17 /** 18 * Here we receive the callback messages from xmlBlaster 19 * @see UpdateFp in CallbackServerUnparsed.h 20 */ 21 static bool myUpdate(MsgUnitArr *msgUnitArr, void *userData, 22 XmlBlasterException *exception) 23 { 24 size_t i; 25 bool testException = false; 26 /* XmlBlasterAccessUnparsed *xa = (XmlBlasterAccessUnparsed *)userData; */ 27 28 for (i=0; i<msgUnitArr->len; i++) { 29 char *xml = messageUnitToXml(&msgUnitArr->msgUnitArr[i]); 30 printf("[client] CALLBACK update(): Asynchronous message update arrived:%s\n", 31 xml); 32 xmlBlasterFree(xml); 33 msgUnitArr->msgUnitArr[i].responseQos = 34 strcpyAlloc("<qos><state id='OK'/></qos>"); 35 /* Return QoS: Everything is OK */ 36 } 37 if (testException) { 38 strncpy0(exception->errorCode, "user.clientCode", 39 XMLBLASTEREXCEPTION_ERRORCODE_LEN); 40 strncpy0(exception->message, "I don't want these messages", 41 XMLBLASTEREXCEPTION_MESSAGE_LEN); 42 return false; 43 } 44 return true; 45 } 46 47 /** 48 * Invoke: HelloWorld3 -logLevel TRACE 49 */ 50 int main(int argc, char** argv) 51 { 52 int iarg; 53 char *response = (char *)0; 54 /* 55 * callbackSessionId: 56 * Is created by the client and used to validate callback messages in update. 57 * This is sent on connect in ConnectQos. 58 * (Is different from the xmlBlaster secret session ID) 59 */ 60 const char *callbackSessionId = "topSecret"; 61 XmlBlasterException xmlBlasterException; 62 XmlBlasterAccessUnparsed *xa = 0; 63 64 printf("[client] XmlBlaster %s C SOCKET client, try option '-help' if you need" 65 " usage informations\n", getXmlBlasterVersion()); 66 67 for (iarg=0; iarg < argc; iarg++) { 68 if (strcmp(argv[iarg], "-help") == 0 || strcmp(argv[iarg], "--help") == 0) { 69 char usage[XMLBLASTER_MAX_USAGE_LEN]; 70 const char *pp = 71 "\n -logLevel ERROR | WARN | INFO | TRACE [WARN]" 72 "\n\nExample:" 73 "\n HelloWorld3 -logLevel TRACE" 74 " -dispatch/connection/plugin/socket/hostname 192.168.2.9"; 75 printf("Usage:\nXmlBlaster C SOCKET client %s\n%s%s\n", 76 getXmlBlasterVersion(), xmlBlasterAccessUnparsedUsage(usage), pp); 77 exit(EXIT_FAILURE); 78 } 79 } 80 81 xa = getXmlBlasterAccessUnparsed(argc, argv); 82 if (xa->initialize(xa, myUpdate, &xmlBlasterException) == false) { 83 printf("[client] Connection to xmlBlaster failed," 84 " please start the server or check your configuration\n"); 85 freeXmlBlasterAccessUnparsed(xa); 86 exit(EXIT_FAILURE); 87 } 88 89 { /* connect */ 90 char connectQos[2048]; 91 char callbackQos[1024]; 92 sprintf(callbackQos, 93 "<queue relating='callback' maxEntries='100' maxEntriesCache='100'>" 94 " <callback type='SOCKET' sessionId='%s'>" 95 " socket://%.120s:%d" 96 " </callback>" 97 "</queue>", 98 callbackSessionId, xa->callbackP->hostCB, xa->callbackP->portCB); 99 sprintf(connectQos, 100 "<qos>" 101 " <securityService type='htpasswd' version='1.0'>" 102 " <![CDATA[" 103 " <user>fritz</user>" 104 " <passwd>secret</passwd>" 105 " ]]>" 106 " </securityService>" 107 "%.1024s" 108 "</qos>", callbackQos); 109 110 response = xa->connect(xa, connectQos, myUpdate, &xmlBlasterException); 111 if (*xmlBlasterException.errorCode != 0) { 112 printf("[client] Caught exception during connect errorCode=%s, message=%s\n", 113 xmlBlasterException.errorCode, xmlBlasterException.message); 114 freeXmlBlasterAccessUnparsed(xa); 115 exit(EXIT_FAILURE); 116 } 117 xmlBlasterFree(response); 118 printf("[client] Connected to xmlBlaster, do some tests ...\n"); 119 } 120 121 response = xa->ping(xa, 0); 122 if (response == (char *)0) { 123 printf("[client] ERROR: Pinging a connected server failed\n"); 124 } 125 else { 126 printf("[client] Pinging a connected server, response=%s\n", response); 127 xmlBlasterFree(response); 128 } 129 130 { /* subscribe ... */ 131 const char *key = "<key oid='HelloWorld'/>"; 132 const char *qos = "<qos/>"; 133 printf("[client] Subscribe message 'HelloWorld' ...\n"); 134 response = xa->subscribe(xa, key, qos, &xmlBlasterException); 135 if (*xmlBlasterException.errorCode != 0) { 136 printf("[client] Caught exception in subscribe errorCode=%s, message=%s\n", 137 xmlBlasterException.errorCode, xmlBlasterException.message); 138 xa->disconnect(xa, 0, &xmlBlasterException); 139 freeXmlBlasterAccessUnparsed(xa); 140 exit(EXIT_FAILURE); 141 } 142 printf("[client] Subscribe success, returned status is '%s'\n", response); 143 xmlBlasterFree(response); 144 } 145 146 { /* publish ... */ 147 MsgUnit msgUnit; 148 printf("[client] Publishing message 'HelloWorld' ...\n"); 149 msgUnit.key = strcpyAlloc("<key oid='HelloWorld'/>"); 150 msgUnit.content = strcpyAlloc("Some message payload"); 151 msgUnit.contentLen = strlen(msgUnit.content); 152 msgUnit.qos =strcpyAlloc("<qos><persistent/></qos>"); 153 response = xa->publish(xa, &msgUnit, &xmlBlasterException); 154 freeMsgUnitData(&msgUnit); 155 if (*xmlBlasterException.errorCode != 0) { 156 printf("[client] Caught exception in publish errorCode=%s, message=%s\n", 157 xmlBlasterException.errorCode, xmlBlasterException.message); 158 xa->disconnect(xa, 0, &xmlBlasterException); 159 freeXmlBlasterAccessUnparsed(xa); 160 exit(EXIT_FAILURE); 161 } 162 printf("[client] Publish success, returned status is '%s'\n", response); 163 xmlBlasterFree(response); 164 } 165 166 { /* unSubscribe ... */ 167 const char *key = "<key oid='HelloWorld'/>"; 168 const char *qos = "<qos/>"; 169 printf("[client] UnSubscribe message 'HelloWorld' ...\n"); 170 response = xa->unSubscribe(xa, key, qos, &xmlBlasterException); 171 if (response) { 172 printf("[client] Unsubscribe success, returned status is '%s'\n", response); 173 xmlBlasterFree(response); 174 } 175 else { 176 printf("[client] Caught exception in unSubscribe errorCode=%s, message=%s\n", 177 xmlBlasterException.errorCode, xmlBlasterException.message); 178 xa->disconnect(xa, 0, &xmlBlasterException); 179 freeXmlBlasterAccessUnparsed(xa); 180 exit(EXIT_FAILURE); 181 } 182 } 183 184 { /* get synchnronous ... */ 185 size_t i; 186 const char *key = "<key queryType='XPATH'>//key</key>"; 187 const char *qos = "<qos/>"; 188 MsgUnitArr *msgUnitArr; 189 printf("[client] Get synchronous messages with XPath '//key' ...\n"); 190 msgUnitArr = xa->get(xa, key, qos, &xmlBlasterException); 191 if (*xmlBlasterException.errorCode != 0) { 192 printf("[client] Caught exception in get errorCode=%s, message=%s\n", 193 xmlBlasterException.errorCode, xmlBlasterException.message); 194 xa->disconnect(xa, 0, &xmlBlasterException); 195 freeXmlBlasterAccessUnparsed(xa); 196 exit(EXIT_FAILURE); 197 } 198 if (msgUnitArr != (MsgUnitArr *)0) { 199 for (i=0; i<msgUnitArr->len; i++) { 200 char *contentStr = strFromBlobAlloc(msgUnitArr->msgUnitArr[i].content, 201 msgUnitArr->msgUnitArr[i].contentLen); 202 const char *dots = (msgUnitArr->msgUnitArr[i].contentLen > 96) ? 203 " ..." : ""; 204 printf("\n[client] Received message#%u/%u:\n" 205 "-------------------------------------" 206 "%s\n <content>%.100s%s</content>%s\n" 207 "-------------------------------------\n", 208 i+1, msgUnitArr->len, 209 msgUnitArr->msgUnitArr[i].key, 210 contentStr, dots, 211 msgUnitArr->msgUnitArr[i].qos); 212 xmlBlasterFree(contentStr); 213 } 214 freeMsgUnitArr(msgUnitArr); 215 } 216 else { 217 printf("[client] Caught exception in get errorCode=%s, message=%s\n", 218 xmlBlasterException.errorCode, xmlBlasterException.message); 219 xa->disconnect(xa, 0, &xmlBlasterException); 220 freeXmlBlasterAccessUnparsed(xa); 221 exit(EXIT_FAILURE); 222 } 223 } 224 225 226 { /* erase ... */ 227 const char *key = "<key oid='HelloWorld'/>"; 228 const char *qos = "<qos/>"; 229 printf("[client] Erasing message 'HelloWorld' ...\n"); 230 response = xa->erase(xa, key, qos, &xmlBlasterException); 231 if (*xmlBlasterException.errorCode != 0) { 232 printf("[client] Caught exception in erase errorCode=%s, message=%s\n", 233 xmlBlasterException.errorCode, xmlBlasterException.message); 234 xa->disconnect(xa, 0, &xmlBlasterException); 235 freeXmlBlasterAccessUnparsed(xa); 236 exit(EXIT_FAILURE); 237 } 238 printf("[client] Erase success, returned status is '%s'\n", response); 239 xmlBlasterFree(response); 240 } 241 242 if (xa->disconnect(xa, 0, &xmlBlasterException) == false) { 243 printf("[client] Caught exception in disconnect, errorCode=%s, message=%s\n", 244 xmlBlasterException.errorCode, xmlBlasterException.message); 245 freeXmlBlasterAccessUnparsed(xa); 246 exit(EXIT_FAILURE); 247 } 248 249 freeXmlBlasterAccessUnparsed(xa); 250 printf("[client] Good bye.\n"); 251 return 0; 252 } We include the header XmlBlasterAccessUnparsed.h on line 15 for full blown access. This header contains a struct with function pointers on all functions necessary to communicate with xmlBlaster. The implementation is multi threaded to receive asynchronous callback messages in the function myUpdate() on line 21. On line 81 we create a client connection instance (one instance of the above struct), which allows us to connect to xmlBaster and work with the server. If we need multiple connections we just call getXmlBlasterAccessUnparsed(argc, argv) multiple times which returns totally independent connection handlers which may be used from different threads if desired.
Have a look at line 82, at the method invocation xa->initialize(xa, myUpdate).
We register our function myUpdate() to receive the callbacks from xmlBlaster.
If a callback message arrives a second thread will deliver it to our function myUpdate().
On line 92 up to 108 we specify a ConnectQos with XML syntax and use this to connect
to xmlBlaster. The XML markup is specified in the interface.connect requirement (see links below).
Note the <callback> section, here we pass the callback server address
which is in our case the local host name and the generated local port of
the synchronous connection. This way callbacks are tunneled through the same socket.
If we omit the <callback> it will be inserted by XmlBlasterAccessUnparsed
and you don't need to call The rest is straight forward, we subscribe to a message, we publish a message we retrieve messages in synchronous mode and clean up at the end. Take care to xmlBlasterfree() resources on the way and to check the exception struct after every invocation to avoid memory leaks.
On line 117 we use the method
Note: If the client wishes to store some client specific data in the XmlBlasterAccessUnparsed instance
we provide a |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Example C |
Redirect logging This example shows how to redirect the logging output from the C lib: 1 /*---------------------------------------------------------------------------- 2 Name: xmlBlaster/demo/c/socket/LogRedirect.c 3 Project: xmlBlaster.org 4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file 5 Comment: Tests redirect of logging 6 Author: "Marcel Ruff" <xmlBlaster@marcelruff.info> 7 Compile: 8 Linux with libxmlBlasterC.so: 9 gcc -D_REENTRANT -Wall -o LogRedirect LogRedirect.c -I../../../src/c 10 -L../../../lib -lxmlBlasterClientC -Wl,-rpath=../../../lib -lpthread 11 See: http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.c.socket.html 12 -----------------------------------------------------------------------------*/ 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <stdarg.h> 17 #include <ctype.h> 18 #include <XmlBlasterAccessUnparsed.h> 19 20 static void myLogger(XMLBLASTER_LOG_LEVEL currLevel, 21 XMLBLASTER_LOG_LEVEL level, 22 const char *location, const char *fmt, ...); 23 static bool myUpdate(MsgUnitArr *msgUnitArr, void *userData, 24 XmlBlasterException *xmlBlasterException); 25 26 /** 27 * Invoke: LogRedirect -logLevel TRACE 28 */ 29 int main(int argc, char** argv) 30 { 31 int iarg; 32 char *response = (char *)0; 33 char connectQos[2048]; 34 XmlBlasterException xmlBlasterException; 35 XmlBlasterAccessUnparsed *xa = 0; 36 37 printf("[client] Try option '-help' if you need usage informations\n"); 38 39 for (iarg=0; iarg < argc; iarg++) { 40 if (strcmp(argv[iarg], "-help") == 0 || strcmp(argv[iarg], "--help") == 0) { 41 char usage[XMLBLASTER_MAX_USAGE_LEN]; 42 const char *pp = 43 "\n -logLevel ERROR | WARN | INFO | TRACE [WARN]" 44 "\n\nExample:" 45 "\n LogRedirect -logLevel TRACE" 46 " -dispatch/connection/plugin/socket/hostname server.mars.universe"; 47 printf("Usage:\nXmlBlaster C SOCKET client %s\n%s%s\n", 48 getXmlBlasterVersion(), xmlBlasterAccessUnparsedUsage(usage), pp); 49 exit(EXIT_FAILURE); 50 } 51 } 52 53 xa = getXmlBlasterAccessUnparsed(argc, argv); 54 55 /* Register our own logging function */ 56 xa->log = myLogger; 57 58 /* connect */ 59 sprintf(connectQos, 60 "<qos>" 61 " <securityService type='htpasswd' version='1.0'>" 62 " <![CDATA[" 63 " <user>fritz</user>" 64 " <passwd>secret</passwd>" 65 " ]]>" 66 " </securityService>" 67 "</qos>"); 68 69 response = xa->connect(xa, connectQos, myUpdate, &xmlBlasterException); 70 if (*xmlBlasterException.errorCode != 0) { 71 printf("[client] Caught exception during connect errorCode=%s, message=%s\n", 72 xmlBlasterException.errorCode, xmlBlasterException.message); 73 freeXmlBlasterAccessUnparsed(xa); 74 exit(EXIT_FAILURE); 75 } 76 xmlBlasterFree(response); 77 printf("[client] Connected to xmlBlaster, do some tests ...\n"); 78 79 /* ping */ 80 response = xa->ping(xa, 0); 81 if (response == (char *)0) { 82 printf("[client] ERROR: Pinging a connected server failed\n"); 83 } 84 else { 85 printf("[client] Pinging a connected server, response=%s\n", response); 86 xmlBlasterFree(response); 87 } 88 89 /* disconnect */ 90 if (xa->disconnect(xa, 0, &xmlBlasterException) == false) { 91 printf("[client] Caught exception in disconnect, errorCode=%s, message=%s\n", 92 xmlBlasterException.errorCode, xmlBlasterException.message); 93 freeXmlBlasterAccessUnparsed(xa); 94 exit(EXIT_FAILURE); 95 } 96 97 freeXmlBlasterAccessUnparsed(xa); 98 printf("[client] Good bye.\n"); 99 return 0; 100 } 101 102 /** 103 * Customized logging output is handled by this method. 104 * <p> 105 * We register this function with 106 * </p> 107 * <pre> 108 * xa->log = myLogger; 109 * </pre> 110 * @param currLevel The actual log level of the client 111 * @param level The level of this log entry 112 * @param location A string describing the code place 113 * @param fmt The formatting string 114 * @param ... Other variables to log, corresponds to 'fmt' 115 * @see xmlBlaster/src/c/msgUtil.c: xmlBlasterDefaultLogging() is the default 116 * implementation 117 */ 118 static void myLogger(XMLBLASTER_LOG_LEVEL currLevel, 119 XMLBLASTER_LOG_LEVEL level, 120 const char *location, const char *fmt, ...) 121 { 122 /* Guess we need no more than 200 bytes. */ 123 int n, size = 200; 124 char *p = 0; 125 va_list ap; 126 127 if (level > currLevel) { /* LOG_ERROR, LOG_WARN, LOG_INFO, LOG_TRACE */ 128 return; 129 } 130 if ((p = (char *)malloc (size)) == NULL) 131 return; 132 133 for (;;) { 134 /* Try to print in the allocated space. */ 135 va_start(ap, fmt); 136 n = vsnprintf (p, size, fmt, ap); 137 va_end(ap); 138 /* If that worked, print the string to console. */ 139 if (n > -1 && n < size) { 140 if (level == LOG_TRACE) 141 printf("%s %s\n", getLogLevelStr(level), p); 142 else 143 printf("{%s-%s-%s} [%s] %s\n", 144 __DATE__, __TIME__, getLogLevelStr(level), location, p); 145 free(p); 146 return; 147 } 148 /* Else try again with more space. */ 149 if (n > -1) /* glibc 2.1 */ 150 size = n+1; /* precisely what is needed */ 151 else /* glibc 2.0 */ 152 size *= 2; /* twice the old size */ 153 if ((p = (char *)realloc (p, size)) == NULL) { 154 return; 155 } 156 } 157 } 158 159 /** 160 * Here we receive the callback messages from xmlBlaster 161 */ 162 static bool myUpdate(MsgUnitArr *msgUnitArr, void *userData, 163 XmlBlasterException *xmlBlasterException) 164 { 165 size_t i; 166 for (i=0; i<msgUnitArr->len; i++) { 167 char *xml = messageUnitToXml(&msgUnitArr->msgUnitArr[i]); 168 printf("[client] CALLBACK update(): Asynchronous message update arrived:%s\n", 169 xml); 170 xmlBlasterFree(xml); 171 msgUnitArr->msgUnitArr[i].responseQos = 172 strcpyAlloc("<qos><state id='OK'/></qos>"); 173 /* Return QoS: Everything is OK */ 174 } 175 return true; 176 } In this example we want to do logging ourself and define the method myLogger() to do so (line 118). The important line (55) is xa->log = myLogger where we register myLogger() to receive all logging output. Note that this should be done directly after the getXmlBlasterAccessUnparsed(argc, argv) function call. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Configure |
These configurations are tested:
These parameters allow to configure the C-client on command line or over the environment (with lower priority):
Testing The testsuite resides in xmlBlaster/testsuite/src/c to compile it use ant: cd xmlBlaster build c-test To run the testsuite invoke build runTests build reportShow And go for a cup of coffee as the complete testsuite will run. How to create the Doxygen documentation The C code is commented to suit the Doxygen tool from http://www.doxygen.org. You need to install Doxygen and GraphViz as described in their manuals to create the html or pdf documentation and additionally man pages: cd $XMLBLASTER_HOME/src/c/doc doxygen Doxyfile Now you can point your browser on $XMLBLASTER_HOME/doc/doxygen/c/html/index.html to view the documentation. After setting export MANPATH=:$XMLBLASTER_HOME/doc/doxygen/c/man:$XMLBLASTER_HOME/doc/doxygen/c++/man you are ready to read the manual pages with for example man XmlBlasterAccessUnparsed.
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 |
This release is stable, but we need to:
C++ remarkThis C SOCKET client library is used as a SOCKET protocol plugin for our C++ client library. With this C++ client library you get all the nice additional fail safe features and XML parsing. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See CODE | HelloWorld.c | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See CODE | XmlBlasterAccessUnparsed.h | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | http://sources.redhat.com/pthreads-win32/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | http://xmlrpc-c.sourceforge.net/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See | http://www.gzip.org/zlib/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | protocol.socket | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | client.c.queue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | client.c.windowsCE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | client.cpp.socket | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | client.cpp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | interface | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See REQ | interface.connect | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See TEST | TestMethods |
This page is generated from the requirement XML file xmlBlaster/doc/requirements/client.c.socket.xml