00001 /* Third VOS tutorial. Local and Remote Vobjects and Messages. 00002 00003 This tutorial file covers: 00004 - Telling to VOS sleep when waiting for network input 00005 - Enabling message queuing on Vobjects 00006 - Retrieving queued messages 00007 - Accessing message fields 00008 00009 This file (vostut3server.cc) is released into the public domain. No 00010 restrictions are placed on its use, distribution or inclusion into 00011 other works. */ 00012 00013 #include <vos/corelibs/vos/vos.hh> 00014 00015 // You must run this program before running vostut3client. 00016 00017 int main(int argc, char** argv) 00018 { 00019 cout << "VOS Tutorial 3 Server\n\n"; 00020 00021 LocalSocketSite localsite(&NoAccessControl::static_); 00022 00023 /* By default, when flushIncomingBuffers() is called it will 00024 check to see if there is any pending data from the network, 00025 act on that data and return. If there is no waiting data, it 00026 will return immediately. For a server application which 00027 spends most of its time waiting for requests this behavior is 00028 bad; it will waste CPU cycles by constantly checking to see if 00029 there is any new data. Using setTimeoutOnSelect you can set a 00030 wait timeout for flushIncomingBuffers(). This means that 00031 flushIncomingBuffers() will sleep either until there is some 00032 network data to process or until this number of seconds has 00033 elapsed. During this time the process will be put to sleep by 00034 the operating system and not using any CPU time. If the 00035 timeout is -1, it will sleep indefinitely until there is some 00036 network activity. */ 00037 00038 localsite.setTimeoutOnSelect(-1); 00039 00040 /* The Vobject API is an abstract class which works for both local 00041 and remote Vobjects (more on this in vostut3client.cc) Here we 00042 will use a C++ cast to convert it into a slightly more concrete 00043 class so that we can access a certain method. A local site 00044 creates local Vobjects, obviously :-) */ 00045 00046 vRef<LocalVobject> primus 00047 = dynamic_cast<LocalVobject*>(localsite.createMetaObject("primus", 0)); 00048 00049 /* There are three ways of handling incoming messages in your 00050 application: you can extend the Vobject and override the 00051 sendMessage() method, you can use addMessageHandler() to set up a 00052 callback or you can enable message queuing (disabled by default) 00053 and call receiveMessage() to retrieve queued messages. This 00054 tutorial demonstrates the third way, but the first two are 00055 generally preferred and are discussed in later tutorials. */ 00056 00057 primus->setQueueMsgs(true); 00058 00059 cout << "vostut3server: Vobject site name is: " << primus->getName() << "\n"; 00060 cout << "vostut3server: Vobject URL is: " << primus->getURL().getString() << "\n"; 00061 vRef<Site> site = primus->getSite(); 00062 cout << "vostut3server: Vobject site is: " << site->getURL().getString() << "\n"; 00063 cout << "vostut3server: Our local site is: " << localsite.getURL().getString() << "\n"; 00064 00065 // The difference between local and remote objects is discussed in 00066 // vostut3client. 00067 cout << "vostut3server: Primus is local? " << primus->isLocal() << "\n"; 00068 cout << "vostut3server: Primus is remote? " << primus->isRemote() << "\n"; 00069 00070 // Our run loop has been expanded: it will now print out any 00071 // messages received by our "primus" object 00072 while(true) { 00073 00074 // This will sleep until something happens, at which point it 00075 // will wake up, parse the inbound message to create a Message 00076 // object, queue the message and return. 00077 localsite.flushIncomingBuffers(); 00078 00079 // This loop prints out any queued messages 00080 while(primus->hasMessageAvailable()) { 00081 00082 // Get the next message that primus has received, removing 00083 // the message from the queue. Note that the Message class 00084 // is reference counted. 00085 vRef<Message> msg = primus->receiveMessage(); 00086 00087 // First print out the message 00088 cout << "vostut3server: " << primus->getName() << " received a message:\n" << msg->getLoggableString() << "\n"; 00089 00090 // Messages have a number of standard fields. The "method" 00091 // field indicates the action the sender is expressing. 00092 if(msg->getMethod() == "tutorial:hello") { 00093 00094 // Another standard field is "from". There is of 00095 // course a "to" field as well :-) 00096 cout << "vostut3server: " << msg->getFrom() << " said hello to us! Isn't that nice.\n"; 00097 00098 try { 00099 /* We can access a particular field using its 00100 name. If no field by that name is present, 00101 then a Message::NoSuchFieldError exception will 00102 be thrown. You cannot access the fixed to, 00103 from, method, etc fields this way (use getTo(), 00104 getFrom(), getMethod() instead). */ 00105 00106 cout << "vostut3server: The word of the day is \"" << msg->getField("word").value << "\"\n"; 00107 00108 } catch(Message::NoSuchFieldError) { 00109 // If we ask for a certain field on a message and it is not present, 00110 // this exception will be thrown 00111 cout << "vostut3server: Oops, no \"word\" field is present, no word of the day for us.\n"; 00112 } 00113 00114 cout << "vostut3server: The fields in this message are:\n"; 00115 00116 // The fields in a message are ordered and so it is 00117 // possible to iterate over them. 00118 for(int i = 0; i < msg->getNumFields(); i++) { 00119 cout << " " << msg->getField(i).key << "=\"" << msg->getField(i).value << "\"\n"; 00120 } 00121 } 00122 } 00123 } 00124 }