Note: Ed's C++ Note is just after SNMP. (This document was written in vim) {{{{ SNMP *SNMP* TCP/IP model: Devices and their working layers Layer Devices or applications 1. Physical repeaters or hubs ( just broadcast) 2. Datalink bridge ( just know ethernet addr, but can isolate broadcaset and switch 3. Internet Rounter or gateways 4. Host to Host IP hosts 7. Applications Telnet, FTP, HTTP, mail *SNMP* Protocals(TCP, UDP) used and their ports FTP(port 20,21) Telnet(23) SMTP(25) HTTP(80) DNS(53) use TCP. DHCP(67,68), BootP(67,68), TFTP(69) SNMP(161,162) use UDP 161(manager/agent port), 162(trap port on manager to receive trap from agent) *SNMP* Typical SNMP Model User Interface Network Management Application (snmp agent not has this) Network Management Engine(know target, create pdu) MDB(Database built with MIB) (vb oid) SNMP (set/get) UDP IPX(Novell's Netware) DDP IP Network Interface (if ethernet layer) *SNMP* 1.3.6.1.2.1 = iso.org.dod.internet.management.mib 1.3.6.1.4.1.161 = iso.org.dod.internet.private.enterprise.motorola *SNMP* MIB MODUELE then MIB Group then MIB object(or table or table entry, then objects as columns in row) *SNMP* MIB MODULE ipMIB MODULE-iDENTIFY some DESCRIPTIONS ::={mib-2 48} where mib-2 is parent of ipMIB and 48 is id of this MIB object *SNMP* First table, then table entry then object (as columns) in the entry ipAddrTable OBJECT-TYPE SYNTAX SEQUENCE OF IpAddrEntry MAX-ACCESS not-accessible STATUE current DESCRIPTION "..." ::={ ip 20 } *SNMP* ipAddrEntry OBJECT-TYPE SYNTAX IpAddrEntry MAX-ACCESS STATUS INDEX {ipAdEntAddr} -- this is key in row ::={ipAddrTable 1} IpAddrEntry ::= SEQUENCE { ipAdEntAddr IpAddress, ipAdEntIfIndex INT, ipAdEntNetMask IpAddress, ... } ipAdEntAddr OBJECT-TYPE SYNTAX IpAddress MAX-ACCESS STATUS DESCRIPTION ::= {ipAddrEntry 1 } SEQUENCE OF means several rows of in a table SEQUENCE {A, B, C } means columns A, B, C in a table *SNMP* No matter the object is a single scalar value or a value in a row in a table, the first oid to get the value of this object always has a .0 appended to the object's oid Then if the tabled object, we will need to append the key to object's oid to uniquely identify a row first, then the object's oid is used to retrieve its value. *SNMP* scalar object has one and only one value *SNMP* PDU of SNMP 1. Ether Header which has target Ether addr(6 bytes) source Ether addr 2. IP Header: IP len, ID No. Fragment TTL, Protocol, checksum, SourceIPAddr, TargetIPAddr, 3. UDP Header SourcePort, TargetPort, UDP len, checksum 4. SNMP SetRequest which has Tag, len, value tuple (as always, but sometimes may have only len, no value), the values or in the following order(remember each value has tag and len!): Version, community, PDU#(means set/get/response/getbulk/trap etc), requestID, errorStatus,errorIndex, VarBindingList which can have several of oid and its value pairs). *SNMP* Common SNMP PDU=Version+Community+PDU Message ::= SEQUENCE { version INTEGER, community OCTET STRING, PDU ::= SEQUENCE { requestType, requestID, errorStatus, errorIndex, then VarBindList ::= SEQUENCE OF {pair of oid and value}}} RequestType ::=SEQUENCE{Get,GetNext,GetBulk,Set,Response,Trap,Inform,Report} Trap has TrapOid(coldStart,warmStart, linkUp, linkDown, authenticationFailure), then timestamp. *SNMP* Purpose of SNMP is F-CAPS ( fault, configuration, accounting, performance and security managements) *SNMP* agent has three main components: Instrumentation Layer (to collect information from a hardware device, then write to MIB), protocol engine and MIB database. The agent is like the following picture SNMP get/set request | SNMP Protocol Engine / \ v v MIB <------>Instrumentation Layer (write to MIB) *SNMP* MIB Compiler MIB Definition (in ASN.1 syntax,oid,type,access) | v MyMIBCompiler (first check syntax) / \ Agent source code(stub) Manager source code (stub to access MIB database) *SNMP* SNMP manager stacks: SNMP Manager application(manager) | SNMP API | SNMP Protocol Engine | Protocol Stack *SNMP* SNMP++ class structure Snmp(ConnectionSession) get,get_next set,get_bulk notify_reg a a (a=aggregate) / \ SnmpTarget Pdu (In future we may hase SecureTarget To ^ a inherite SnmpTarget) | | CTarget(=agent) Vb a a / \ / SnmpSyntax / ^ --------------|------------------------- |/ | | | | | Oid OcteStr Uint32 Counter64 Address Int32 ^ ^ | | -------------------- -------------------------- | | | | | | | TimeTick Gauge32 Counter32 Ipaddr MacAddr IpxAddr GenAddr ^ ^ | | UdpAddr IpxSockAddr *SNMP* SNMP++ example code int status; Snmp snmp(status); if ( status != SNMP_CLASS_SUCCESS ) { cout<msg(arg) //where -> is a an overloaded operator which must return a pointer of pPerson is equivalent to : (smPersonPtr.operator->())->msg(arg) //where smPersonPtr is an *obejct* of a class that is a wrapper of class Person, in the wrapper smPersonPtr there is a data member of *person, so smPersonPtr.operator->() returns the pointer pPerson, then the right msg(...) is invoked on the pointer. ---------- inline Person & PersonPtr::operator*() { if ( pPerson==NULL ) allocate; return *pPerson ; } *C++* String inStr ; cin >> inStr ;//cin must accept char *, so must have String::operator const char*() which returns member of str_ in String *C++* stream example: inline ostrem & operator << ( ostream & p_ostr, const Complex & p_rhs ) { p_ostr<> ) we use file scope definition for overloading. *C++* Generally, a class that requires a destructor, copy constructor, or assignment operator also needs the other two member functon. especially when a class allocates dynamic memory or other resouce. *C++* Do you know how to add timestamp in your output whenever you call cout? answer: you can do the following: ostream & operator<<(ostream &out, const int & a ) { printf( "%d\n", time(0) ) ; //must use printf! using cout causes recersive // call when you call cout<<100 ; printf ( "%d\n", a ) ; return out ; } *C++* Definition of this: MyClass const * this ; //you can not change the pointer value, because of const here. *C++* C++ is a statically and strongly typed language especially when there is no polymorphism of a class ( that is no inheritance and no base class pointer or base class reference for dynamic binding ( or polymorphism ) ). *C++ static object* static object always initialized as soon as they are declared. *C++* do you know cout, cin, cerr, and clog are static object whose constructors are invoked even before your main function? *C++* It is a *must* that you define a default constructor if you do something like: const CString myString ; //no initializer for myString, a must! CString *pStringArray = new CString[20] ; // all 20 objects of CString will invoke default constructor and then address of the first object will be assigned to pStringArray. Note: On CC compiler, this is not a must! *C++* If a composite class contains instances of other classes as data members, then the instances of these other classes must be initialized in the initialization list of the composite class(the initialization is using copy constructor, if copy constructor is private, then the initialization will fail). constant data member must also be initialized in the initialization list of the composite class. Same with reference data members. If a data member's class defines a default constructor, then the data member can be omitted from the initialization list of the composite class, this means that the default constructor will be invoked to initialize this data member. *C++* a composite class B containing reference of class A object, keeping const A & in B constructor must have (A &) cast or const_cast(a), otherwise get: Error: Initializing A& requires an lvalue. class A { public : A ( ) { cout << "A()"< (a) ) { } A &m_ra ; } ; *C++* distinguish between copy constructor and assignment operator: A a ; A a1 = a ; or A a1 ( a ) //copy constructor of A called A a2 ; a2 = a ; //assignment operator of A called A &a3 = a ; //neither copy constrctor nor assignment operator called *C++* example uses of copy constructors: CPoint pt1(3, 3) ; CPoint pt2(pt1) ; //equivalently CPoint pt2 = pt1 ; CRectangle rect(pt1, CPoint(7, 7)) ; // another example is return by value from a function, omitted here *C++* example copy constructor: CRectangle::CRectangle(const CRectangle &argRect) : //must pass in by //reference! otherwise, if pass in by value, the copy constructor will be //invoked when pass in by value, leading to infinite recursive call of //the copy constructor! m_origin(argRect.m_origin), m_corner(argRect.m_corner) { } another example: inline CString::CString (const CString &p_str) :m_length(p_str.m_length),m_str(new char[p_str.m_length+1]) { strcpy(m_str,p_str.m_str ) ; } copy constructor does not need to test this==&rhs because the object has not be constructed yet when copy constructor is called, so this does not exit at all. Now compare it with assignment operator overloading = CString & CString::operator=(const CString &p_rhs) { if ( this == &rhs) { return *this ; } delete [ ] m_str ; m_str = new char [ p_rhs.m_length+1] ; strcpy(m_str, p_rhs.m_str) ; return * this ; } *C++* derived class lives *within* the scope of its immediate superclass *C++* pointer to member function Class CExample { public int func(int, char* ) ;} ; void foo ( ) { CExample ex ; int ( CExample::pMemFunc ) ( int, char* ) ; //define a pointer to member //function in class CExample pMemFunc = &CExample::func ; //assign to pointer to member functon of //CExample (ex.*pMemFunc) ( 100, "abc" ) ; //invoke the pointer to member function } *C++* Questions: 1) how to convert C++ to C code keeping inheritance, hint use structure to convert the class into structure, then in the derived structure, add a pointer to the structure for the base class 2) show implementation of copy constructor and how to use it. Class::method( ) convert to Class_S_method(StructForClassDataMember * pStruct ) *C++* C++ feature: function overloading, readonly variables, default value in function parameters, inline, constructor,initialization list, and destructor, overloading of constructor, operator overloading, try and catch, name space, inheritance, object pointer, object reference for dynamic binding of function invocation or polymorphism, template, funciton template, class template, C++ has scope operator ::, C++ add a new scope, class scope, in which there is data member and member functions, and private, protected and public. C++ compatible with C, actually a super set of C. namespace myNameSpace { template //same as: template class D:public B //scope of derived class and base class, inheritance { public: D ( ):B() { } D (const A & a_rA):B(..), m_rA(a_rA) { } //initialization list D(const D & a_rD ):B(a_rD) { //copy constructor,need to invoke base class copy constructor! } D & operator = ( const D & a_rD) { if (this == &a_rD)....omitted } virtual void vBBB() { .... } //vBBB already declared in class B virtual void vFun()=0 ; //new virtual in class A void fun( ) { try { } catch (error &e) { }} void fun(int a=100 ) { ... }//function overloading, default value //member function pointer below void anotherFun(){ int (A::*pf)(int) ; pf=&A::func; A a; (a.*pf)(100); } inline int someFun() { A::someFunInA(); MyType a; a.xxx(); } //static virtual ~D() { ... } //must be virtual because we have our own new virtual function here protected: private: cont A &m_rA //readonly ATemplateClass *m_pAtc ; //must have to be a class type! } ; //end of class D } ; //end of myNameSpace *C++* constant pointer or constant referent: const char * str = "hello" ; //what str is pointing to is a constant object // can still do: str = "mmm" ; because "mmm" is // constant object char * const str = "hello" ; //pointer is constant, can not do str="mmm" // or str++ const char * const str = "hello" //both pointer and referent are constant *C++* Difference between pointer and reference: Pointer Reference Pointer: can change to pointer to other object of same type Reference: can not change to refer to other object after initialization Pointer: can assign NULL to a pointer Reference: there is no such thing as null reference. reference must refer to a concrete object of same type. Pointer: has pointer arithmatic operation Reference: does not have arithmatic operation Pointer: has polymorphism through base class pointer, (through virtual member function that derived class overrides). Reference: has polymorphism through base class reference Reference does not have dereference. And can not be reassigned. Note: interestingly a reference parameter is typically implemented as a pointer in the stack frame of a function. Pointer: we can have something like: int ** ppInt ; Reference: we can not have int && rrInt ; *C++* For a virtual function, if there is a default value for a argument of the virtual function in a base class, this argument *always* override the default value of the argument of the virtual function in all subclass. *C++* static_cast<> and reinterpre_cast<> usages: int iNum1 = 1 ; double dbNum2 = static_cast(iNum1) ; void * pArg = &iNum1 ; double * pDbl = reinterpret_cast(pArg) ; *C++* dynamic_cast returns a pointer object of MyTypeToCast if succeed, otherwise return null e.g. CSquare is a descendant of CBaseObject CBaseObject *pCBaseObject = new CSquare(5) ; CSquare *pCSquare = dynamic_cast(pCBaseObject) ; if ( pCSquare != NULL ) { pSquare->findDiagonal( ) ; } *C++* typeid operator accepts pointer or reference typed object, returns a reference to a type_info object. type_info class represent information of the operand of typeid operator. int main() { CPerson * pPers = new CEmployee ; CPerson &rPers = *pPers ; //rPers is an alias of CEmpolyee object bool test ; test=(typeid(pPers)==typeid(CPerson*)); //1, pPers declared as CPerson* ; test=(typeid(*pPers)==type(CEmpolyee)); //1, not typeid accept rererence type, and *pPers refers to CEmployee test=(typeid(rPers)=typeid(CEmpolyee)); //1, rPers is alias of CEmployee test=(typeid(&rPers==typeid(CEmployee*));//1, adress of CEmployee } *C++* static: if a function or a variable declared as static in a file, this function lives only within that file. A static variable within a function preserve its value across function invocations. A static member function in a class does not have this pointer of the class. It can only access static data member of the class. A static member variable in a class is a class scope wide variable, we can access it even without creating an object of the class. *C++* inline function must be placed in header file, otherwise, compiler can not do the text substitution for client who uses the inline function. *inline* compiler will refuse inline your inline function if there is loop, calls to a virtual function, or recursive function call. If your inline function is invoked through function pointer, compiler will also not do inline for you. *C++* function pointer int func1( char * int ) ; int main ( void ) { int ( *pFunc) ( char *, int ) ; pFunc = &func1 ; //where & is optional, but better to have it int num = (*pFunc) ("hello", 7) ; //where * is also optional, //but better to have it return 0 ; } *C++* Inheritance class CPriorityQueue : public CQueue { public: CPriorityQueue(bool (CElemType::*)(const CElemType&) = &CElemType::operator<) ; //CElemType is a class, here we have a pointer //pointing to member function of CElemType, //the memeber function accept const //CElemType & and return bool, //it has a default function < virtual CPriorityQueue & insert(const CElemType &) ; //this member //function also declared in CQueue, as //virtual CQueue &insert(const CElemType&) ; protected: bool (CElemType::*pCompareFn)(const CElemType &) ; //member function //pointer to save member function pointer //passed in through CPriorityQueue constructor } ; inline CPriorityQueue::CPriorityQueue(bool (CElemType::*cmp)(const CElemType &)) : CQueue( ), pCompareFn(cmp) { } int main ( void ) { CPriorityQueue pq(Date::operator>); pq.insert(Date("1/1/90")) ; CQueue * pCQueue = &pq ; //if use CQueue & rCQueue, reference, same! pCQueue->insert(Date("1/2/91")) ; //dynamic binding to use insert //function in CPriorityQueue class, not CQueue class! } *C++* only friend and constructor of base class are not inherited into derived class. *C++* it is impossible to use dynamic binding in constructor or destructor, only static binding of the virtual function is possible! Because in constructor the descendant is not completely built, and in destructor the descendant may have been partially destroyed! So never call virtual functions in constructor or destructor. *C++* assigning a derived class value object to a base calss value identifier, caused the information(eg. data member value) in derived class to be lost *C++* virtual destructor, Suppose CEmpolyee is derived from CPerson, CEmployee has CString data member in it CPerson *pCPerson = new CEmpolyee(...) ; delete pCPerson ; //Now if did not declare virtual ~CPerson, then only object of CPerson destroyed, not CEmployee. When we declared a base class destructor as virtual, then derived class object will be destroyed, followed by based class object. Add virtual keyword to your destructor name when you have virtual funtion in your class. *C++* Abstract class CAbstract { virtual method(...)= 0 ; //pure virtual function .... } ; As long as CAbstract contains pure virtual function, we can not construct an object out of it. *Interface class* Interface class typically has no data member, no constructor, has pure virtual functions to define the interface and a virtual destructor *C++* How compiler convert C++ with virtual function into C code: virtual pointer and virtual table for derived class: CSquare is derived from CDisplayObject. CDisplayObject { virtual void draw(...) { ... } virtual void resize(...) { ... } virtual void rotate(...) { ... } virtual void display(...) { ... } int size ; } ; CSquare : public CDisplayObject { virtual void draw(...) { ... } virtual void resize(...) { ... } virtual void rotate(...) { ... } int color ; int center ; } ; Then CSquare has following data structure containing vptr: CSquare: vptr size (of CDisplayObject, not CSquare) color center And vptr is pointer to vtbl which has the following data structure: vtbl for CSquare(array of function pointers): msg0 --> CDisplayObject::display() in vtbl of CDisplayObject class msg1 --> CSquare::draw() equavalent to CSquare_S_draw() in linker msg2 --> CSquare::resize() msg3 --> CSquare::rotate() Actually vptr is an array of function pointers. vptr points to the first element in the array of the function pointers. Remember CDisplayObject has a vtbl for all its virtual functions(similar to CSquare). Then how compiler invokes and dispatches resize(): CSquare *pCSquare = new CSquare(...) ; (*(pCSquare->vptr[2]))(...) *C++* Multiple inheritance name conflits(will need to use scope operator to resolve): Ancestor1 msg1() msg2() ^ | Base1 Base2 msg1() msg1(int); msg2( ); mem mem ^ ^ | | \ / \ / Derived msg3() //Derived has mem from Base2 and Base1, doing //mem++ in Derived::msg3() will be ambiguous; //but doing Base1::mem++ will not be ambiguous main() { Derived der(...) ; der.msg1() //invokes Base1::msg1() der.msg1(5) //invokes Base2::msg1(int) der.msg2() //error, ambiguous, both Ancestor and Base2 has msg2() Base1 * pBase1 = &der ; pBase1->msg2() ; //invokes Ancestore1::msg2() der.Base1::msg2() ; der.Base2::msg2() ; } *C++* Repeated inheritance Person name() and m_name ; / \ Customer Employee \ / CustomerEmployee class Person { protected: String name() const { return m_name ; } private: String m_name ; } ; //if not using virtual inheritance of base class, both Customer and Employee //has its *own* name() method inherited from Person. Causing CustomerEmployee //to have two name() method //Using virtual base class inheritance gurantees there will be only one name() //in CustomerEmployee. //And *any* invocation of name() automatically call Person::name with virtual //base class inhritance(there is no Empolyee::name() nor Customer::name())! class Customer:virtual public Person { .... } ; class Empolyee:virtual public Person { .... } ; class CustomerEmployee:public Customer, public Employee { .... } ; *C++* Dominance rule with virtual inheritance: Person name() / \ Customer Employee name() //dominating all call of name()!!! \ / CustomerEmployee Let us say Empolyee override Person's name(), but Customer does not, then Employee::name() will dominate *any* executation of name() funtion! That is each invocation of pPerson->name() ; pEmployee->name() ; pCustomer->name() ; pCustomerEmployee->name() ; will call Employee::name()!!!! *C++* Also with virtual inheritance, descendant class constructor must invoke ancestor's constructor, not only descendant's immediate base class constructor! CustomerEmployee::CustomerEmployee(...):Person(...),Customer(...),Employee(...){ } *C++* function template: In a .h file: template //same as: template //We can even specify a default type for CType: //like: template inline CType & min ( const CType &arg1, const CType & args ) { return arg1 < arg2 ? arg1:arg2 ; } This requires operator < : template inline bool operator<(const CType &lhs, const CType &rhs) { return lhs < rhs ; } Another function template example: template CType min (const CType array[], int size) { CType minElem(array[0]) ; for(int i = 1 ; i < size ; i++) { if(array[i](d1, 4) ; //specify CType must be double, //compiler applies double to 4 } *C++* If int min(int, int) is instantiated multiple times in program, then there will be multiple linkage error, or increasing size of program. So we can specify that it will be instantiated only once by adding the following in the program file: template int & min(const int&, const int&) ; *C++* class template examples: In .h file: template class Node { friend class Queue ; //Queue is not class name, must have //to be a class name! friend ostream & opeartor<<(ostream&,Queue&); protected: Node(const ElemType&) ; //constructor function ElemType elem; Node *next ; //must have for Node to be a class name } ; template class Queue { friend ostream& operator<<(ostream&,Queue&); public: Queue(); //consturctor function no need for virtual ~Queue(); virtual Queue& insert(const ElemType&); ElemType remove(); bool isEmpty(); protected: Node * front ; Node * back ; } ; ---- In .C file: template //must have this line for *each* method definition inline Node::Node(const ElemType& el):elem(el),next(NULL) { } template inline Queue::Queue():front(NULL),back(NULL) { } template Queue& Queue::insert(const ElemType &el) { Node* pNode = new Node(el); if(isEmpty()) {front=back=pNode;} else{back->next=pNode; back=pNode;} return *this ; } ---= template class SetIterator { public: SetIterator(const Set&); void reset(); bool atEnd(); void advance(); protected: Set& set ; } ; int main() { Set nameSet; nameSet.insert("abc").insert("def") ; SetIterator namesIter(nameSet) ; for(namesIter.reset();namesIter.atEnd();namesIter.advance()) { //....} } ---= template class Array { public: Array(); Array(const ElemType & initValue); Array(const Array&); }; int main() { const int low = 1; int high = 20 ; Array strArray; Array strArray1; //error: high is not constant } ---= Using template of template: List > corners ; ---= template class PriorityQueue:public Queue { public: PriorityQueue(bool(ElemType::*)(const ElemTYpe&)=&ElemType::operator<); ElemType first(); virtual PriorityQueue & insert(const ElemType &); protected: bool(ElemType::*pCompareFn)(const ElemType&); } ; template inline PriorityQueue::PriorityQueue(bool(ElemType::*cmp)(const ElemType&)) : Queue(), pCompareFn(cmp) { } template inline ElemType PriorityQueue::first() { if(isEmpty()) throw EmptyError; return front->elem ; } --= Queue and Queue has no relationship, even though Square is derived from DisplayObj. We can not say that Queue is a subclass of Queue at all. *C++* exception: declaration in .h file: char & String::operator[](int index) throw(SubscriptError); definition in .C file: #include "SubscriptError.h" char & String::operator[](int index) { if(index<0||index class auto_ptr { public: explicit auto_ptr(CType *artPtr=NULL):m_ptr(argPtr) {} ~auto_ptr() {delete m_ptr; } CType * operator->() const {return m_ptr; } CType & operator *() const {return *m_ptr; } private: CType * m_ptr ; } ; void func() { List *pNames = new List; auto_ptr > pNameList(pNames) ; pNameList->insert("abc") ; //upon exit of this block, destructo of auto_ptr will automatically delete //pNames // Remember when using auto_ptr, you can not have two auto_ptr to point same // object, otherwise, the object will be deleted twice! //also do not use dynamic array in auto_ptr, like std::auto_ptr //apStringArray(new std::string[100]) ; because ~auto_ptr calls delete not //delete [] } ----full template example ---------- A.h #include "iostream.h" //using namespace std; //if use std:: then this line not needed. class CompanyA { public : void sendClearText(const std::string & msg ) { cout<<"sendClearText"< class MsgSender { public: void sendClear(const MsgInfo & info) { std::string msg ; Company c ; c.sendClearText(msg ) ; } void sendSecrete(const MsgInfo & info ) { } } ; template class LoggingMsgSender : public MsgSender { public: using MsgSender::sendClear; //to make method in Base accesible! void sendClearMsg(const MsgInfo &info) { cout << "sendClearMsg" << endl ; sendClear(info) ; } }; -- A.C #include "A.h" #include int main ( void ) { LoggingMsgSender lms ; MsgInfo msgInfo ( "aaaa" );//char allowed becasuse have const in prototype lms.sendClearMsg ( msgInfo ) ; std::list l ; //if using namespace std not in header file, must have std:: //conversely,if std:: used, no need for using namespace std in //header file return 0 ; /* output: sendClearMsg sendClearText */ } Note: MsgSender above is a template class, if you want to specialize it to CompanyZ: template<> //means I will specialize a template class with a real class type class MsgSender { .... } ----end full template example --------- template T func ( const T a, const T b ) { return aa ; } int a = func ( 5, 6 ) ; //will get 100! ---- *C++* I hate global variable: real customer cases: iDEN OMC multiple windows changing same global variable, causing configuration of T1/E1 line incorrect. Very difficult to debug. So scope is very important. *C++* Namespace namespace is like a class, need to use scope operator. In .h file namespace myexamples { class String { //.... } ; inline bool operator==(const String &, const String&); template class Queue { protected: class Node { //.... } ; } ; void func1(const String&); void func2(int) ; int num1; int num2; int num3; } ; In .C file #include "myexamples.h" void myexamples::func1(const myexample::String& str) { //... } void myexamples::funcs(int i) { //...; } inline myexamples::String & myexamples::String::operator=(const myexamples::String &argStr) { //.... } int main() { myexamples::String str("hello") ; myexamples::func1(str); myexamples::num2=9 ; myexamples::func2(myexamples::num2) ; using examples::num1 ; //to import num2 into this main function scope num1=0 ;//operating on myexamples::num1 //once num1 imported to live in main(), we can not do int num1 //:error, multiple declaration using namespace myexamples; myexamples::num3=100; } *C++* How to use STL: #include "assert.h" #include #include #include using namespace std; //must have this on SPARC machine int main ( void ) { list L; vector V; V.insert(V.begin(), 3); assert(V.size() == 1 && V.capacity() >= 1 && V[0] == 3); return 0 ; } ---- *C++ guidline* 1) Use const, enum and inlines(for min(a,b) #define) not to use #define. You must assign a value to a const immediately it is declared. And constant can not be initialized twice! class A { static const int myConst =1; }; *C++ Iterator, const pointer, const pointer contents* std::vector vect; vect.push_back(100) ; const std::vector::iterator iter = vect.begin ( ); //like char *const p *iter = 10 ; //pointer contents can change ++iter ; //error, can not change pointer value std::vector::const_iterator cIter = vect.begin(); //like const char *p //*cIter = 10 ; //pointer contents can not change. ++cIter ; //pointer value can change *virtual destructor* Declare your destructor if and only if your class contains at least one virtual function. If a class object is to be accessed through pointer of a base class(for polymorphism), then the base class must have a virtual destructor. *It is not good to inherite a class that is not intended to be inherited, especially the class does not have virtual destructor, because when calling delete ptrBaseClass, even though ptrBaseClass is pointing to DerivedClass object, only BaseClass portion will be destroyed, DerivedClass part is not destroyed. *destructor* Destructor should not throw exception, otherwise, resource leak or undefined behavior of program. It some exception does throw in destructor, the destructor must catch it and deal with it itself. *explicit* explicit keyword means not implicit type conversion by compiler. *inheritance and copy constructor or assignment operator* You need to call copy constructor (assignment operator) of base calss when defining copy constructor (assignment operator) of derived class. CDerivedClass::CDerivedClass(const CDerived &rhs) : CBaseClass(rhs) { ... } CDerivedCalss&CDerivedClass::operator=(const CDerivedClass &rhs) { ...CBaseClass::operator=(rhs) .... return *this; } *Must use matching delete to new,delete [] to new []* *Smart pointer*: immediately store the object that you new'ed in smart pointer to prevent resource leak in case there was exception thrown between execution of new and the storing of the new'ed object into the smart pointer. *Pass by reference to const* Prefer pass by reference to const over pass by value. It is typically more efficient for the type that you defined, and it avoids the slicing problem(when a function argument is a CBaseClass type, the CDerivedClass data member information is sliced away when you tring ot pass value of an object of CDerivedClass to the argeument of the function). *static data member or static object within a function is not multithread safe!* *For built in type, use pass by value, not by pass by reference. *C++* For operator olverloading, suppose you define operator + overloading as a member function, the following will not compile Rational r = 2 + rational(5) //becasue compiler unable to promote 2 to Rational. So you must define a global operator + overloading function: Raional & operator+(const Rational &lhs, const Rational &rhs) ; Type conversion never applied to receiver of message. So we need to use a file scope definition for an operator overloading that must permit an implicit conversion of either the left or right operand. *Why C++ could be less efficient than C?* because 1) when calling copy constructor: when copying data member ( and each data member needs to copy its internal data members) 2) dynamic dispatch and binding of virtual function. 3) With multiple inheritance, you may need to use CDerivedClass:virtual public CBase, and the most derived class is responsible for initializing the CBase class. And this initialization is small. *public inheritance models is-a relationship: CStudent -> CPerson, student is a person. *Never redefine an inherited non-virtual function, (because you will not only hide the function name in base class with your function name in derived class, but also change behavior of base class's function to the derived class function behavior if you call through pointer of derived class *In derived class, never redefine default parameter value in function that is inherited from base class. *It is useless to use inheritance when base class does not have virtual function. Because you can use composition not inheritance. *typename is required here: template const C& container typename C::const_iterator iter ( container.begin() ); //because we want C::const_iterator to be a type *C++* Container: vector, deque, stack, queue, list, set, multiset, map, multimap, and string. Note string also is a container How to iterator through container: vector vectorObject; vector::iterator i ; for ( i = vectorObject.begin(); i != vectorOjbect.end(); i++) { cout<<*i; } ---- Compiler automatically generate the following for you if you do not declare them: 1) default constructor, 2) default copy constructor, 3) default assignment operator and 4) default destructor ---- template class Rational {public: ... friend const Rational operator*<(const Rational &lhs, const Rational &rhs>; //must have this friend otherwise the following code would not compile: //Rational oneHalf(1,2); Rational result=oneHalf*2; because second //parameter for * must be Rational not int. There is no way for compiler //to do instantiate from int to Rational, compiler is not that smart Note this friend is not accessing private member of Rational, it is just for declaration purpose. } ; template const Rational operator *(const Rational&lhs,const Rational&rhs) ---- When is good time to use inheritance: You have virtual function in your base class. You also need to declare virtual destructor in your base class. -- Otherwise use composition ---- *Template metaprogramming! template struct Factorial { enum { value = n*Factorial::value}; }; template<> //specialization of the template struct Factorial<0> { enum { value = 1 } ; } ; int main ( void ) { int i = static_cast (Factorial<5>::value) ; cout<-------Item virtual Human* makeHuman()=0 item *m_pItem ^ virtual Item * makeItem()=0 ^ | virtual void link(Human *, item *) | | ^ | | | | | ConcreatFactory Student Book Human* make(){ return new Student} ----- aggregate relation usually means using *m_pItem or &m_item in Human 2) Builder: Builder is used to make very complex object(component) (such a list(array) of 3 students each with a book). It can use Abstract to make Human first, then add the Human to component. Component -------(n) Human Builder has following structure: Builder ----------------------AbstractFactory(to make Human) Component* makeComponent() 3) Singleton: class Singleton { singleton() {count++; if(count>1) cerr<<"error"; exit(1); } ~singleton() {if(count>0) count--; } static int count ; }; class Singleton { static singleton *getinstance(){if(m_psinstance==0) {new singleton;} return m_psinstance ; } static m_psinstance ; protected: singleton() {} }; Problem with singleton: if singleton already deleted, and other people do not know and try to use it, then crash. 4) Prototype: prototype is a class instance can be cloned with a clone method clone(newAttributeToModify). clone method ususally calls copy constructor. 5) Adapter: Assume class B does not implement some behavior(say display), however we wish to display. Then we can use the following structure to do display: Interface virtual display()=0 ^ | Adaptor -------------- B Usually there are many other class to inherite Interface, pInterface can point to other ConcreteInterface(such as Adaptor), then call display to have polymorphism. 6) Bridge is used to get different run time behavior of an aggregate class depending on the concrete class that it actually aggregates: Bridge -------------Figure void draw() ^ ^ Figure *m_pFigure | | Circle Triangle So the behavior draw() of Bridge depends on what m_pFigure really points to. 7) Composite is a class containing instances of its super class, example: CFileBase void create(), void delete() ^ ^ ^ | | a (a means aggregate) CFile | | (no other method needed, CDirectory (Now CDirectory is Composite) becasue CFileBase already CFileBase *m_pFileBase have enough methods) int m_NumOfCFileBase 8) Decorator is a class to provide additional functionalities for a base class without increasing the depth of inheritance, eg: CEmployeeTaxReporter virtual void report()=0 ^ ^ | | CEmployee_FedTaxReporter | ^ | | | CEmployee_StateTaxReporter--CEmployee_CityTaxReporter (CEmplyee_CityTaxReporter must implment report()) (CEmpolyee_CityTaxReporter is now a Decorator) 9)Proxy: a class that is a subclass of a BaseBehaviorClass. HighCostComplexClass inherits BaseBehaviorClass. Proxy also inherits BaseBehaviorClass, but is used to create HighCostComplexClass only when necessary: BaseBehaviorClass ^ ^ | | HighCostComplexClass--- ProxyClass (a proxy) HighCostComplexClass *m_pHCC A proxy is similar to Decorator, but does not provide additional functionalities(Decorator provide additional functionalities) 10)Facade: Provide simple interface to a complex system. CGovernment (Facade) virtual behaviorInterface()=0 int m_iPowerLevel ^ ^ ^ ^ | | | | FederalGov StateGov CityGov VillageGov Based on m_iPowerLevel, the behavior (through behaviorInterface) of FederalGov can be different, and FederalGov now becomes Flyweight(like a CGenericGov), and StateGov,CityGov, VillageGov can be eliminated. 11) Flyweight: a base class has an instrinsic attribute, and extrinsic attribute. A Flyweight inherits the baseclass. Potentionally many class can inherit the baseclass. Based on instrinsic attribute, a Flyweight exhibit different behaviors, eliminates the needs of those many class. See example above. 12) ChainOfResponsibility: User of a chainOfResponsibility can get the best helps from either Handler1, Handle2...HandlerX (Handler_i form a chain) ------- | | | | CUser------------Handler- (must Handler *m_pNext) m_pHandler virtual void HandleIt()=0 ^ ^ ^ | | | Handler1 Handler2... HandlerX The CUser, through m_pHandler get the best Help or HandleIt() from the chain of Handler1, Handler2, or HandlerX 13)Command: command is an intermediate between application and executor(target), it can keep state information of targets CCommand 1----1CApplication ^ 1 | | CFigure_Command Figure n void execute() ^ ^ | | Circle Square When CFigure_Command.execute, then it will delegate all the way down to Circle and Square. 14) Iterator: responsible to traverse a list CIterator 1----1CList 1----n CElement 15) Observer: observer is used to receive change notification of someOjbectChange CSomeObject-----CIterator-----CList----CElement(CElement=Observer) changeSomething() m_pIterator 16) Memento: to remember previous state information of an element. CIterator---CList----CElement----CMemento m_pMemento int m_iPreviousStateOfElement 17)State: upon a state change, behavior change to different class. (The behavior of CTarget will be like a Bridge) CTarget---S t a t e ^ ^ ^ | | | State1 State2 State3 18) TemplateMethod: TemplateMethod is to exhibit behavior of baseClass together with subclass CBaseClass CBaseClass void templateMethod() { ^ pureVirtualMethod1(); | pureVirtualMethod2(); ConcreteClass localBaseClassMethod();} pureVirtualMethod1() = 0; pureVirtualMethod2() = 0; localBaseClassMethod() { ...} ; 19) Visitor: without modify code of the class user of visitor, the behavior of the users is different. CUser----CVisitor-----CAnotherDifferentUser ^ | CVisitor1 *End C++ Pattern* }}}} End C++ ============================================================================= {{{{ C#.NET 1. C#: .NET archicture and specifications MyApp in C# (must be conforming to Common Language Specification Type) ------------------------------------------------------------ Base Class Libraries DataAccess GUI Security XML/SOAP Threading FileIO Debugging et. al ------------------------------------------------------------ The Common Language Runtime(loads MetaData in Common Intermediate Language) (Commone Intermediate Language, MetaData in DLL or EXE. MetaData describes type vividly: base class, interfaces, methods, members) ------------------------------------------------------------ Common Type System (specification[for:class, structure, interface, enumeration, delegate]) ------------------------------------------------------------ Common Language Specification ------------------------------------------------------------ 2. C#: Common Language Specification makes sure that every one (every language) agrees on the same type definition) 2a. C#: MetaData describes type vividly: base class, interfaces, methods, members). .Net-aware compiler is responsible for producing the MetaData for each type in assemblies. MetaData (manifest) also describes assembly in vivid detail (including version information). Because of Metadata, each module in assembly is 100% completely self-describing. It even describes the external assembly that the module uses. MetaData is backbone of .NET technologies. 3. C#: C# does not have delete keyword. C++ and even Java have it. 4. C#: support interface-based programming like COM. In COM, interface means interface to executable *binary* COM code! 5. C#: what are difference between attributes and properties? 6. C#: struct type in CTS(common type system) is sealed(can not be derived), value type(allocated on stack, not on heap). We should be able to derive struct from some interface type. 7. C#: interface type contains only pure virtual methods only. }}}} End C#.NET ============================================================================= {{{{ VisualC++ As a MCP ( Microsoft Certified Professional since 2003, I should have written more on Visual C++, but I just can not find time. *User Interface: Window structure: WindowFrame, Client Area. Under title of window Frame, we have menu, under menu, we have toolbars. At the button of the Window Frame, we have status bar. User interface includes dialog box. For each icon on tool bar, we could have tool tip. User interface is created by using the resource editor. Properties sheet is also user interface. Create a CFormView to host controls. Validate user input with DDV, transfer and process user input from a form or dialog box with DDX. Provide context sensitive help, with web page. Create secondary thread, Use ActiveX user interface controls. Create ActiveX User Interface Control, or COM component by using ATL, SDK or MFC. * Application Behaviors: Display data to an on-screen window and printer. Implement help for window * Persistent Data: use windows registry to make application data, window size and position and settings persistent. Use CArchive serialization facilities to save and restore structured application data. * Adding database support: ActiveX Data Object (ADO) to access database. * Com(Component Object Model): Binary standard for software objects in different language, platforms to communication with each other. ActiveX is COM to be placed in web page or dialog box to perform a self-contained function. * Use ActiveX Template Library(ATL) to create COM. * How to use COM: application and COM can use service provided by a COM * Use MFC to create Active X Controls, then use ActiveX Template Library(ATL) to craete Active X controls. * Internet Programming: Dynamic HTML to create user interface. Add Web-browsing capabilities to applications and components. Develope application to create ActiveX documents-documents that can be hosted by Internet Explorer and edited on web. * Error handling, Debugging, and Testing * Deploying desktop application: Use installShield to automate installation process of application and COM. Use Microsoft Zero Administration (ZAW) to perform intelligent installation for users. * What is MFC regular DLL and MFC extension DLL * How command routed between user interface and a handler function * What is MFC Document/View Architecture, MFC Drawing, Printing and Print Preview archiecture * Access database with ADO, ODBC or RDO. *VisualC++* Used ISAPI technologies, active service document(ADS), FTR and database APIs to 1) retrieve customer open DR from CDMA database to web page, 2) create issue logger for customer log issues against HAP product. //Example code to retrieve from or write to database, and to construct dynamic //webpage to display to your users!!!! class CMyISAPIExtension : public CHttpServer { void NewRecord(CHttpServerContext *pCtxt, LPCTSTR customer_name, LPCTSTR headline, LPCTSTR date, etc...); void ViewRecord(CHttpServerContext * pCtxt, long recordID) ; void Default(CHttpServerContext *pCtxt) { StartContent(pCtxt) ; WriteTitle(pCtxt) ; *pCtxt <<_T("Retriving from CDMA database....") ; CDatabase aDB ; try { adb.Open("ODBC;DSN=customerSupport",....) catch(){...} ; CRecordset aRs(&aDB) ; //call aRs.GetODBCFieldInfo() to get fieldNames; while(!aRs.IsEOF()) { *PCtxt<<_T("") ; //You depends *pCtrx<<_T("strings") ; to write whatever you want to web //page dynamically! You can construct dynamic pages to user!!! aRs.GetFieldValue(....) ; //to get field values, write to row } //to change DB: I called aDB.ExecuteSQL() ; aRs.Close() ; aDB.Close() ; EndContent(pCtxt) ; } } In MyISAPI.cpp file: CMyProjectApp theApp; // Visual C++ has this always except for DLL. //which is actually CMyProjectApp, through pointer to CWinApp, we get //polymorphism. BEGIN_PARSE_MAP(CMyISAPIExtension, CHttpServer) ON_PARSE_COMMAND(Default, CMyISAPIExtension, ITS_EMPTY) DEFAULT_PARSE_COMMAND(default, CMyISAPIExtension) ON_PARSE_COMMAND(NewRecord, CMYISAPIExtension, ITS_PSTR, many ITS_PSTR..) ON_PARSE_PARAMS("customer_name issue_headline....") END_PARSE_MAP(CMyISAPIExtension) *VisualC++* Document then View architecture in MFC so my ADS also have Document View architecture!. *CWinApp uses MyPRoject classes derived from CFrameWnd, CDocTemplate, CView and CDocument. *CFrameWnd inherited by CToolBar, CChildView, CStatusBar class CMyProjectApp : public CWinApp { public: virtual BOOL InitInstance() { AfxOldInit(); Enable3dControls() ; SetRegistryKey(_T("generated app") ); LoadStdProfileSettings(); CSingleDocTemplate * pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME, RUNTIME_CLASS(CMyProjectDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CMyProjectView)) ; pDocTemplate->SetServerInfo(IDR_SRVR_EMBEDDED,IDR_SRVR_INPLACE, RUNTIME_CLASS(CInPlaceFrame)); AddDocTemplate(pDocTemplate) ; m_server.ConnectTemplate(clsid, pDocTemplate, TRUE) ; EnableShellOpen(); RegisterShellFileTypes(TRUE); CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo) ; if (cmdInfo.m_bRunEmbedded || cmdInfo.m_bRunAutomated) { //if launched as OLE server COldTemplateServer::RegisterAll(); return TRUE ; } m_server.UpdateRegistry(OAT_DOC_OBJECT_SERVER); ProcessShellCommand(cmdInfo); m_pMainWnd->ShowWindow(SW_SHOW); }//end InitInstance COldTemplateServer m_server ; Run(); OnIdle(); and ExitInstance(); } ; In CMyProejctApp.cpp static const CLSID clsid= { 0x705ee6c1, 0x8fc8, 0x4838, {0xb2, ....} } ; BEGIN_MESSAGE_MAP(CMyProjectApp, CWinApp) ON_COMMAND(ID_FILE_NEW,CWindApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinAPP::OnFileOpen) ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP() In MainFrame.h: 1. class CMainFrame:public CFrameWnd { CMainFrame(); DECLARE_DYNCREATE(CMainFrame) virtual BOOL PreCreateWindow(CREATESTRUCT& cs); //just call CFrame::PreCreateWindow(cs) ; CStatusBar m_wndStatusBar ; CToolBar m_wndToolBar ; afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct) ; //for ON_WM_CREATE } In MainFrame.cpp: BEGIN_MESSAGEMAP(CMainFrame,CFrameWnd) ON_WM_CREATE() END_MESSAGE_MAP() int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { CFrameWnd::OnCreate(lpCreateStruct) ; m_wndToolBar.CreateEx(this, ) ; m_wndStatusBar.Create(this); m_wndStatusBar.SetIndicator(, , ) ; m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY) ; } ---- If for ADS, in addition to MainFrame we have IpFrame.h IpFrame.cpp which means in place. In place has ToolBar, and COldResizeBar, but no StatusBar. Also has OnCreate function class CInPlaceFrame:public COldDocIPFrameWnd { CToolBar m_wndTooBar ; COleResizeBar m_wndResizeBar ; virtual BOOL OnCreateControlBars(CFrameWnd* PWndFrame, CFrameWnd* pWndDoc) { } //to create control bars on the container application of this inplace //frame. } ; *OLE Server is contained in container, server(SrvrItem) is like a view operating on document Doc. IpFrame is like MainFrm* *Active X server = COM server object with GUI contained in a container. It has: Properties, Methods, and Events. ---- *document template* Document template is a connection between documents, frame window and view, through the pointer of which we can setServerInfo for ADS. It is added by CMyProject::InitInstance() which show the main frame window, accept drag and drop. Anyone(Doc, View, Frame that inherite CCmdTarget can response to message) *Inheritance sequence CObject<-CCmdTarget<-CWnd<-CDialog class CMyProjectDoc:public pulbic COleServerDoc //ADS { public: CMyProjectSrvrItem * GetEmbeddedItem() { return (CMyProejctSrvrItem*) COleServerDoc::GetEmbeddedItem();} virtual COleServerItem * OnGetEmbeddedItem(); {CMyProjectSrvrItem *pItem=new CMyProjectSrvrItem(this) ; } virtual BOOL OnNewDocument() {COleServerDoc::OnNewDocument();} virtual void Serialize(CArchive &ar) { if(ar.IsStoring() {...}else{...} }; virtual CDocObjectServer * GetDocObjectServer(LPOLEDOCUMENTSITE pDocSite) { return new CDocObjectServer(this, pDocSite) ; } } ; class CMyProjectView::public CView { protected: DECLARE_DYNCREATE(CMyProjectView) public: CMyProjectDoc * GetDocument() {return m_pDocument;}; virtual void OnDraw(CDC * pDC) { CMyProjectDoc *pDoc=GetDocment() ; pDC->TextOut(10,10, "Hello World") ; } virtual BOOL preCreateWindow(CREATESTRUCT &cs) {return CView::PreCreateWindow(cs) ; } virtual BOOL OnPreparePrinting(CPrintInfo * pInfo){return DoPreparePrinting(pInfo);//to popup print dialog } virtual void OnBeginPringing(CDC * pDC, CPrintInfo * pInfo); {pDC->StartDoc(); ....} virtual void OnPrepareDC() { //CDC::StartPage; } virtual void OnPrint(); //CDC::EndPage(); //CDC::EndDoc(); virtual void OnEndPrinting(CDC * pDC, CPrintInfo * pInfo) ; } ; ---- ------------------ class CMyProjectSrvrItem:public CDocObjectServerItem { public: CMyProjectSrvrItem(CMyProjectDoc * pContainerDoc) ; CMyProjectDoc * GetDocument() const { reutrn CDocObjectServerItem::GetDocument(); } virtual BOOL OnDraw ( CDC* pDC, CSize &rSize) { CMyProjectDoc * pDoc = GetDocument() ; pDC->SetMapMode(MM_ANISOTROPIC) ; pDC->SetWIndowOrg(0,0); pDC->SetViewPortExt(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY)); pDC->SetWindowExt(3000,3000); SetScrollSize(MM_TEXT, bigSize); return TRUE ;} virtual BOOL OnGetExtent(DVASPECT dwDrawAspect, CSize & rSize) { return CDocObjectServerItem::OnGetExtend(dwDrawAspect, rSize) ; } virtual void Serialize(CArchive &ar) {CMyProjectDoc * pDoc=GetDocument(); pDoc->Serialize(ar) ; } } ; CDocument::UpdateAllViews() calls CView::OnUpdate(), then CView::OnPaint() then CView::OnDraw(); ------------------ //Example code to popup a CDialog to do FTP: class CFTPDialog : public CDialog { public: CFTPDialog(CWnd* pParent = NULL); protected: virtual void DoDataExchange(CDataExchange* pDX);//to collect and {CDialog::DoDateExchange(); DDX_Text(pDx,IDC_USER_NAME,m_userName);} //verify data from user DECLARE_MESSAGE_MAP() } Visual C++ has CWinApp the App; It has a resouce.h which is included by MyProject.rc. resouce.h defines parameters for BUTTON position, Frame ID. menuId, MyProject.rc is then compiled by Visual C++ resource compiler into binary object and then included in the MyProject.exe executalble file. Command callback function is corresponding to these IDs defined in resouce.h For example in MyProjectApp.cpp file: BEGIN_MESSAGE_MAP)CMyProjectApp, CWinApp) ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) .... END_MESSAGE_MAP() *ActiveDocumentServer* class must have data member COleTemplateServer m_server; *Thread in Visual C++* AfxBeginThread(funcPtr, ptrData) ; UINT ThreadFunc( LPVOID pParam); for normal worker thread. AfxBeginThread(RUNTIME_CLASS(CMyUIThread)) for UI thread *How to free a non_modal dialog?* Override virtual function PostNcDestroy(...){AfxGetMainWnd()->SendMessage(WM_USER_APPLY,0, ptrData);} *Registry API: WriteProfileString() GetProfileString() WriteProfileInt() GetProfileInt() *To make data members in your class CMyClass serializable: class CMyClass: public CObject { CMyClass() { //must have default constructor to set to default value } DECLARE_SERIALIZE do IMPLEMENT_SERIALIZE in .cpp file CDoc::Serialize(CArchive &ar) ; }; *To make a topmost window: CWnd::SetWindowPos(&wndTopMost, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE) ; *To enable a window: CWnd:EnableWindow(TRUE); *to get WinHelp: call CWnd::WinHelp(); *to get HTMLHelp: call HTMLHelp(NULL,"MyHelp.chm",HH_DISPLAY_TOPIC,0); *In window about synchronization, we have: CCriticalSection -->Only one thread in *ONE* PROCESS CMutex, CSemaphore, CEvent --for multiple process CCriticalSection m_cs; CSinglelock sl(&m_cs) ; sl.lock(); .... sl.unlock() ; ---- CPropertySheet sheet; CPropertyPage page1; shett.AddPage(&page1); sheet.DoModal(); CPropertyPage::OnUpdatePropertyPage1(){SetModified(TRUE);} ---- Window messages have four types: 1)Window(such as window on focus message) 2)Command 3)UserInterfaceUpdateCommand 4)ControlNotification *message processing sequence: HarwarEvent->WindowMessageQueue->MyAppMessageQueue(which also accepts message from PostMessage)->MyAppMessageLoop(which also accepts messages from SendMessatge)->MyWindowProcedure->WindowDefaultMessageProcedure *CDC: CMyView::DIsplayDraw(nX, nY) { CClient ClientDC(this); CDC memDC; memDC.CreateCompatibleDC(&ClientDC); memDC.SelectObject(&m_maskBitmap); ClientDC.BitBlt(nX,nY,WIDTH,HEIGHT,&memDC,0,0,SRCCOPY); } *Create a process in Windows: ::CreateProcess("MyApp.exe",0,0,0,FALSE,0,0,0,&StartupInfo,&ProcessInfo); *How to popup contextMenu menu.LoadMenu(IDR_CONTEXTMENU), pContextMenu=menu.GetSubMenu(0); pContextMenu->TrackpopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, point.y,point.y,AfxGetMainWnd()); ---------- ---------- ---------- ----------- ---------- ---------- *COM* All COM object must get support from Registry Key for COM Runtime class to find dll of the COM object. All COM object must have the following interface(pVtable, member function pointers): pVTable-> &QueryInterface &AddRef &Release (the above 3 are in IUnknown interface) &Encode &Decode (the above 2 are user specific interface) &SendData &ReceiveData (the above 2 are in ICommunication interface) COM object optionally have the following for Visual Basic: &GetTypeInfoCount &GetTypeInfo (for type library) &GetIDsOfNames &Invoke(...) (the above 4 are in IDispatch interface) Through InProcServer32 in Registery(see below), TypeLibarry describes to Visual Basic types of parameters and how many parameters the COM object user interface have. *RegistryKey* HKEY_CLASS_ROOT CLSID 64CE32A0-6B03-11d3-9532-0080CTFAOC3E PROGID="EncodeServer.Encoder.1" VersionIndependentProgId="EncodServer.Encoder" InProcServer32="C:\MyCompany\EncodeServer.dll" (Com Runtime class use it) ThreadModel=Apartment TypeLib Wind32=C:\MyCompany\EncodeServer.dll *How COM created?* CoCreateInstance->QueryRegistry->InProcServer32->LooadLibrary-> DllGetClassObject->new ClassFactory->IClassFactory::CreateInstance-> new EncodeServer->IUnknow->InterfaceFunctionToCall->backToClientOfThisCom So, ::CoCreateInstance(CLSID_Encoder,NULL, CLSCTX_INPROC_SERVER,IID_IEncoder,&pMyEncodeServer) ; pMyEncodeServer->EncodeString("HelloWorld", iMyKey) ; ---- CoInitializeEx(COINT_MULTITHREADED...) CoMarshalInterThreadInterfaceInStream() ---- *ATL to create COM object: class ATL_NO_VTABLE CEncoder:public CComObjectRootEx, public CComCoClass, public IEncoder {...} * int main( ) { ::CoInitialize(NULL); IEncoderPtr pServer; pServer.CreateInstance(__uuidof(Encoder)); pServer->EncodeString("HelloWorld",100) ; } *MFC: steps to create ActiveX control: 1) Add Properties, 2) AddMethods, 3)AddEvents 4)CreatePropertyPage(which is ATL COM object, so need to insert it. Modify dialog of property page. 5) Implement OnDraw. *Internationalization = Unicode = _T("String") in Windows MFC. *Testing: Unit test, box test, system integration test, regression test, beta test, stress test. * Installation of application: use InstallShield to wrete Setup program to create disks and automatically install and register application/COM component or to Uninstall. Installation can be disk, CD, web-based deployment or network based deployment. C++ aggregation means a class contains data member attribute of the class that being aggregated. *Visual C++* Have solid knowledge of at leaset the following: 1) VC++, SDK, MFC 2) User interface and behavior with menu, dialog, scroll views, split views, toolbar, tooltip, multi_thread in Visual C++, context-sensitive helps. Drag and Drop. 3) Persistent Data with registry, database programming, MS SQL server. Internet programming with ActiveX document, ISAPI, socket, DHTML, XML and some javascript. 4) COM server, COM client, ActiveX controls, 5) Testing and error handling 6) Desktop application deployment *Visual C++* Thread creation sequence in VC++: CWinThread* pThread = AfxBeginThread (ThreadFunc, NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); pThread->m_bAutoDelete = FALSE; pThread->ResumeThread (); // Sometime later DWORD dwExitCode; ::GetExitCodeThread (pThread->m_hThread, &dwExitCode); if (dwExitCode == STILL_ACTIVE) { // The thread is still running. } else { // The thread has terminated. Delete the CWinThread object. delete pThread; } *Visaul C++: contents that I knew Windows GDI, CDC, pen, brush Mouse(need mouseEvent function to get user inputs) Menu MFC Collection (Array, list, map) MFC Serialization and File I/O Controls (buttons, list box, edit control, scroll bar, static controls) Dialog box(Modal/Modeless, property sheets, common dialog(FileDialog, PrintDialog, FindReplaceDialog, ColorDialog, FontDialog) Document/View architecture ScrollView, HTML view, treeView, ListView(like windowExplorer) MFC MDI, Splitter Windows, ToolBar, StatusBar, Rebar. Printing/PrintingPreview Timer/IDLE Processing Bitmap, Palettes Common controls(Slider, spinButton, tooltip, imageList, ComBoxEx, Progress AnimationControl, IPAddressControl) Thread and ThreadSynchronization COM(UnknowInterface(AddRef,Release,QueryInterface, IDL, registries) Clipboard and DragDrop(with OLE as middleman between DropTarget and DropSource) Automation(with IDispatch (Invoke, GetIDsOfNames, GetTypeInfo, GetTypeInfoCount), Dual Interface ATL ActiveXControlServer(IOleObject, IOleControl, IOleInPlaceActiveObject, IOleInPlaceObjectWindowless, IOleCache, IViewObjectEx, IDataaObject, IQuickActivate, IPersistMemory, IPersistProperBag, IPersistStorage, IPsrsistStreamInit, IDispatch, IProvideClassInfo2, ISpecifyPropertyPages, IPerPropertyBrowsing, IConnectionPointContainer) Ambient property. ActiveXControlContainer(IOleContainer,IOleInPlaceFrame, IOleClientSite, IOleInPlaceSite, IOleControlSite, IOleInPlaceObjectWindowless, IDispacth, IDispatch, IPropertyNotifySink) ActiveControl License issue for developer and user Each control has: Property Event Method SmartPointer ==== class ATL_NO_VTABLE CATLDiceObjj : public CComObjectRootEx,//for IUnknown functions public IDispatchImpl, public CComControl,//to talk to client public IPersistStreamInitImpl, public IOleControlImpl, public IOleObjectImpl, public IOleInPlaceActiveObjectImpl, public IViewObjectExImpl, public IOleInPlaceObjectWindowlessImpl, public IConnectionPointContainerImpl, public IPersistStorageImpl, public ISpecifyPropertyPagesImpl, public IQuickActivateImpl, public IDataObjectImpl, public IProvideClassInfo2Impl<&CLSID_ATLDiceOb, &DIID__DDiceEvents, &LIBID_ATLDICESVRLib>, public IPropertyNotifySinkCP, public CComCoClass { . . . }; ==== }}}} End Visual C++ ============================================================================= {{{{ Java *Java* I used Jave to create a game software Pacman! posted on my peronal website, please take a look yourself, play it. You can also get my source code from that website! *Java* Difference between Java and C++ C++ uses const, Jave uses final C++ supports multiple inheritance, Jave does not, but supports multiple inheritance of interfaces Java requires the file name should be the same as class name. Everything in Jave is class, C++ does not have be everything in class, but C++ is a super set of C, backward compatible with C C++ has virtual and Java have abstract for polymorphism. *Final class* If a class is declared final, it can not be inherited. * C++ uses cout << " string"; Jave uses System.out.println("string"); * C++ uses #include; Java uses import * C++ uses CMyClass : public CBaseClass for inheritance; C++ allows multiple * inheritance. Java uses extends ( to replace : public); Java can implement several interfaces. Interfaces in Java has only pure virtual(or abstract) methods only and no data member (except static data member which is class-wide data, strictly speaking, it is not data member of the class). In Java, subclass needs to call super() in its constructor. * C++ has abstract class (which may have data member) containing pure virtual methods. Interfaces in Java has only pure virtual(or abstract) methods only and no data member. * Java has two types: primitive data type and reference type, C++ has pointer type also. * We can say that C++ and Java have same control structures. Comments, Class structure (note C++ class method can be inline) and program structure are also the same. * Java memory garbage collection, C++ you clean up after yourself if you use "new" *Each Java class implicitly inherites Object class. * The usage of static variable and method in Java is the same as in C++. * Is a = inheritance. Has a = composition. * Java uses finally block in try...catch..., C++ uses catch(...) * Java and C++ use throw(Execption name) to do rethrow ==== *Java* For me, absolutely no problem with my OOP or C++ or Java, I wrote Pacman in Java and posted it publicly on my own website in the world with my source code publicly(www.geocities.com/hans_ji). Everything is OOP. ==== *Java* my Pacman public class Pac extends JFrame { //data members Pac() { super(); Container c = getContentPane(); c.setLayout(new FlowLayout()); JTextField text=new JTextField(); c.add(text); JButton b= new JButton(); c.add(b); b.addActionListener(new ActionListener(){public void actionPerformed(ActoinEvente) {...} } setSize(100,100,show()); } public void pain(Graphics g_) //I must implement this! { //repaint buttons,labels; draw walls, cherries, money //e.g. g_drawRect(0,0,10,10); g_.setColor(); } } *Java* How to make Pacman move: call Graphics::copyArea() and clearRect() public static void main(String args[]) { CMyApp myApp = new CMyApp(); myApp.addWindowListener(new WindowListener() {public void windowClosing(WindowEvent e) { System.exit(0);} } class StartAnimationHandler implements ActionListener { // must implement actionPerformed(ActionEvent e) function! } *My Pacman Pac.java architecture: more than 2000 lines of code! * Pacman uses Color, Graphics, ContentPane, Font,JFrame(JApplet), JLabel, Rectangle, Ellipse, Arch, JTextField, EventListener, JButton, MouseListener, KeyListener, FlowLayout, JPanel, Timer. JFrame ^ | Pac | / | \ | | | | | Pacman--|-----------Ghost Wall ButtonHandlerTimer StartAnimHandler | / \ \ | / \ | / | / | \| V | V / | | | |---->MoveObject | ActionListener <-- | | | | draw() | | | | | move() | | | | | | | | | | | Sleeper Money Cherry | \ / | ------- | | | +------------------------+ WindowHandler | V WindowAdaptor import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Pac extends JApplet //because I want to put on web so JApplet, //usually JFrame { private Pacman _pacman; private Ghost _ghosts [ ]; private Cherry _cherries [ ]; private Money _moneys [ ]; private Wall _wall; //then some JButton, scoreLabel, etc. public void init() //to initialize all private data members. { //also arm all button with addActionListener to add call back //functions to start timer, move Pacman left or right. setVisible(true) ; } public void paint ( Graphics g_ ) { _leftButton.repaint ( ); _pacman.draw() ; //and draw all other objects including wall, buttons } //.... other private functions public static void main ( String args [ ] ) { Pac pac = new Pac ( ); /* comment cout for JApplet! WindowHandler wh = new WindowHandler ( ); pac.addWindowListener ( wh ); */ } } class Pacman { public void draw() //to set color, eyes, mouth public void move() //to determine which way, where and how far can move public void detectCollisionsWithMoneyCherriesGhosts() //also update score! public void detectGameOver() ; } class Ghost { ... //pretty similar to Pacman except they moves randomly and //ramdom color } class Wall { ... //to draw() with color.... } class Money { .... public void draw() //if not eaten yet, draw class Cherry { } class ButtonHandler implements ActionListener { //to set moving direction of Pacman public void actionPerformed ( ActionEvent e ) { if ( e.getSource ( ) == _leftButton ) { if ( _pacman.getMovingDirection ( ) != Pacman._LEFT ) { _pacman.setMovingDirection ( Pacman._LEFT ); _pacman.clearImage ( ); _pacman.draw ( ); _pacman.move ( ); } elseif.... { } //then detect whether pacman collide with anyone else. } } class WindowHandler extends WindowAdapter { public WindowHandler ( ) { super ( ); } public void windowClosing ( WindowEvent e ) { System.exit ( 0 ); } } *JApplet: automatic calling sequence by Java Environment: init->start(when user returns to browser)->paint->stop(when user leaves browser) *JApplet and JFrame has paint() function. They are not subclass of JComponent, which has paintComponent method. * Menu can only be attached to object that provides method setJMenuBar, such objects are JFrame and JApplet. * JFrame contains JMenuBar which contains JMenu which contains JMenuItems(CheckBox type and Radio type) *Thread has states: start, run, interrupted, stop, sleep (wait), yield states. -------------- Multimedia part * class Applet { getImage(URLOfImage, fileNameOfImage); URLOfHTMLOfTheApplet getDocumentBase( ); LocationOf.ClassFileForTheApplet getCodeBase( ) ; getParameter( ) //get parameters for the applet specified in HTML file getAppletContext( ) //get context of applet = browser AudioClip GetAudioClip( ); Play(URLLocationOfSound) ; } * AppletContext.showDocument(URL) to display document in browser * JFrame::setCursor(Cursor.WAIT_CURSOR) to show wait hour glass * Socket ServerSocket::accept(). Socket::getOutputStream() and * Socket::getInputStream( ) . InputStream::read( ) to read input * class Graphics { drawImage(Image, x, y, ImageObserver); //ImageObserver to update the display image as the image is being downloaded from internet. } * class ImageIcon { paintIcon(ComponentToDisplayImageOn, ImageIcon, Graphics, x, y); getImageLoadStatus ( ) ; } * class AudioClip { play(); loop(); stop(); } * class Manager implements Player { addControllerListener(ControllerEvent) { .... if ( RealizeCompleteEvent ) { clip detected and loaded already ... } } Component getVisualComponent ( ) ; getControlPanelComponent ( ) ; } -------------- End Multimedia part * JFileChooser { showOpenDialog( ); getSelectedFile( ) ; setFileSelectionMode( ) ; } * class File { toURL ( ) ; } * class Timer { Timer ( milliseconds, ActionListener) { } .... } * sun.jdbc.odbc.JdbcOdbcDriver is a subprotocol of Microsoft's ODBC * DriverManger.getConnectin(URL) to try to establish a connection to the database. * Connection.createStatement("SQLStatement") to create statement * Statement.executeQuery( ) to query database, it returns ResultSet. * ResultSet.next to iterate through the result set. * ResultSet.GetMetaData to get column name. ResultSet.getcolumnType( ) * ResultSet.SetMetaData to set column name. * Connection.setAutoCommit; Connection.rollback(); Connection.commit(); * CMyServlet : implements Servelet { init ( ServletConfig ) throws ServletException ; getServletConfig ( ) ; } HttpServlet is an example of CMyServlet { service ( ) { //.... doGet(HttpServletRequest, HttpServletResponse ) { myHttpServletRequest.getparameter ... myHttpServletRequest.getCookies( ).getMaxAge( ) myHttpServletRequest.getCookies( ).getValue( ) myHttpSservletRequst.getSession( ).getValue( ); //putValue( ) } doPut(HttpServletRequest, HttpServletResponse ) { HttpServletResponse.getOuputStream.getWriter( ); } }; } * Many of today's applications are three-tier distributed applications ( user interface(can be HTML page), business log(can be stored procedures), and databae access) ---- * RMI: CMyRMI extends UnicastRemoteObject implements Remote { myMethod throws RemoteException } * RMI object on a server must be compiled with rmic To register rmi object: rmiregistery("//localhost:1099/myRMIObject") # on command line then call Naming.rebind( ) ; * For client to look up a RMI object on a server, call Naming.lookup which returns a Remote reference * Networking: socket types: stream (continuous) socket, and datagram socket. ---- Hashtable.put(key, value), Hashtable.get(key), Hashtable::containsKey(key) * Vector( ), Vector( initialCapacity ), Vector(initialCapacity, increaseAmount) * primitive data type wraper: Byte, Short, Integer, Long, Float, Double, * Boolean and Character. All of these inherite from Object * Vector::addElement, Vector::removeElement, Vector::firstElement, * Vector::isEmpty * Stack extends Vector * Property extends Hashtable, it is persistent, like COM property is persistent * Array::binarySearch(), Array::equals(anotherArray), Array.fill(items), Array.sort() * List is an interface, implemented by ArrayList, LinkedList and Vector. * Java Collection live in jave.util package. Collection is an interface, from which Set and List derived. CollectionObjec.Interator( ) to get an Iterator. * IteratorObejct.hasNext( ) == true means collection has next element * IteratorObject.next( ) returns the next object in the collection * ListObject.clear( ) removes elements from the ListObject * ListObject.shuffle( ), ListObject.reverse( ). * CollectionObject.toArray( ) * Array::binarySearch() is a static method, Array::sort() also static method Array::fill( ) and Array::equals( ) and Array::asList( ) also static methods; * Array::asList( ) provides a "list" view for programmer of an array. Any change to the "list" is actually on the array * Map stores (key, value) pair. We have TreeMap which is ordered ( binary ordear), and HashMap. * Java Bean is like MFC COM object which has Property which can be 'get' and 'set', Property change can generate events to notify server(container of the com object). }}}} End Java ============================================================================= {{{{ MyOrgnationa1 *MyOrg1_C++* Did you ever use call back function in your class? what must be in your class to use callback function(static function!) We know that when a thread is created, it will execute a callback function to to some task. Show how to use C++ to design and implement a generic threadBase class allowing user of the threadBase class to specify his own function for the thread to execute, and once the thread is launced, user's function will be executed. Note one restriction: everything must be in class or classes, that is, using a global scope C function to implement user's thread function is not allowed. Tricks: You may want to use static function, or this pointer The model is: CThreadBase virtual void vThreadFunction(someData) = 0 int run(); ^ | CUserThread virtual void vThreadFunction(someData) Can you design a generic base thread class, which can be inherited and once lauched, the user's thread function is run, note everthing must be 100% object-oriented. Note: I did this myself without referring to any book!!!! Can I ask you how to #ifndef THREADBASE_H #define THREADBASE_H /** ThreadBase: a base class to be inherited and extended by a thread class ThreadBase just defines run and stop functions. User has to implement the pure virtual function **/ #include "iostream.h" #include "strstream.h" #include "taskLib.h" #include "assert.h" #include "CONSTANTS.h" class ThreadBase { private: //copy constructor and assignment not supported ThreadBase(const ThreadBase &a) const ThreadBase & operator = (const ThreadBase &a); virtual int vWorkFunction() = 0; //pure virtual,okay to be private! can // be protected also! inline static int //return 0 on success, -1 on error workFunction //must be static!! if not, error!! because thread api expect ( // a C type function, which must be a static function //although it can be private! //do you know why in Java we always have a static method: //public static void main(String args[]) // the reason is the same: must have C type function! int threadBasePtr //pointer to baseClass ) { ThreadBase *tb = (ThreadBase *) threadBasePtr; if (tb == NULL) { return -1; } tb->vWorkFunction(); //call user's function actually return 0; } protected: int tid; //following parameter must be set in derivedClass, for ease of debug char derivedThreadName[CONSTANTS::stringSize]; public: inline ThreadBase() { tid = ERROR; bzero(derivedThreadName, CONSTANTS::stringSize); } inline int //return -1 on error, 0 on success run ( ) throw (APIError) { if ( (tid = taskSpawn(derivedThreadName, CONSTANTS::TASK_PRIORITY, 0, CONSTANTS::TASK_STACK_SIZE, (int(*)(...))&(ThreadBase::workFunction), (int)this, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) { //this pointer is important ! throw APIError("taskSpawn"); return -1; //not needed } return 0; } inline int stop() throw (APIError) { if (taskIdVerify(tid) == ERROR) { return -1; } if (taskDelete(tid) == ERROR) { throw APIError("taskDelete"); return -1; } return 0; } inline virtual ~ThreadBase() { } //must be virtual otherwise when delete //pThreadBase will not delete derived class object(only //ThreadBase object deleted!) }; #endif //How to use ThreadBase: CMyThread::CMyThread():ThreadBase() {strcpy(m_derivedThreadName,"CMyThread");} int CMyThread::vWorkFunction(){ while(1) {....} } int main(void) {ThreadBase *ptb=new CMyThread(); ptb->run(); } ==== *MyOrg1* Purpose of statistics manager is to collect statistics data from user component every 30 minutes, and keep statistics files for up to 2 days, which can be up loaded to OMCR *MyOrg1* Object Oriented Analysis Modeling : How to convert requirement into OOP design document. This is very important step and sometimes very difficult, but I can show you how easy it is! 1) read requirement document, identify all the most important use cases, and the actors that the use cases are interacting with, then on Rational Rose use case digram, draw the use cases and the actors. For example for Statistics Manager, use cases: Initialize, ReceiveRegistration, BroadcastRequestStatistics, ParseWriteStatistics, ManageStatisticsFiles, actor is user components (payload card component), software load component and disk. 2) Then for each use case, we automatically have a controller class, which we call it useCaseController class, and for each actor, we have actorInterface class, for example requestStatistics use case, we have requestStatisticsController class. For the interface class we usually can refine it further during refining phase of class design. For example actorInterface becomes publisher and subscriber classes. 3) Within a use case, read document to find out nouns, which potentially can become a class, but some nouns may just be an attribute of some other class, and become a data member of the other class. Then go to Rational Rose, create the classes. With the potential classes identified, read the requirement document, find the verbs that are interacting with the nouns ( classes ), then draw sequence diagrams. Remember the direction of the verb interaction is very important, the target of the direction determins that the methods (or functions) must be in the target class. Look at the following sequence diagram, base on the direction or arrows, you will get the classes and methods in each class instantly. BudgetAcct Manager TeamPlayer Employee Product | | (Timesheet) |- Make ->| | | |<-LogTime- | | | |-CheckOverTime->| | | | |-CheckQuantity--|-----------|-------->| |<-CheckMoeny-| | | | |-GetEmplInfo-|----------------|---------->| |<-MakeBonus -| | | |-SendBonus --|----------------|---------->| 4) Refine each class and class interaction: look at the interfaceActor class first, sometimes it may be combined with other class, and could be gone. For example, if Bank is a actor, a Customer is a class that we are designing, the interfaceActor class, may become an Account class simply, and will be gone. During the class refining phase, we need to identify the is-a and has-a relationship between classes. Remember is-a means inheritance in C++, which may display polymorphism, and has-a means aggregation or composition. If composition, we may want to put a data member as attribute in a class. For example, Broadcaster is a thread, Receiver is a thread, so we have a base class ThreadBase. Normally for actorInterface class, we can refine it further, for example, the actorInterface class in Statistics Manager becomes Subscriber class, and Publisher class. ---- And for example, read the sentence, "income of employee", here Employee is a class, but income may be as simple as an integer attribute data member in Employee class, or income may be as complex as a new class Account for Employee to manage his money. Now assume Account is an account for Employee, it looks like the Employee will aggregate or own an Account. But depending on your problem domain, this may not be the case, an Account may be owned by a Bank and Employee may just simply use the service provided by the account. example -------- PayloadCmpActor Pub Sub RequestStatisticsController Broadcaster Receiver The message sequences are like this: 1. controller tells broadcaster to send request 2. boradcaster tells Pub to send requst to Actor, 3. controller tells receiver to recieve statistics from actor 4. receiver uses Sub to get statistics (pub and sub uses distributed messaging service from GoAhead company API) The direction of message is extremely important in sequence diagram! Remember if a message is pointing to a class then the class is the receiver of the message, it means the class must provide function of this message, so for each class just collect all the message that is pointing to it, then you get the class diagram automatically!!!! So easy to do UML OOP design!!!! So we have class diagram like the following: RequestStatController | | | | (v = uses) v v Broadcaster Receiver | \ / | (V(in) = inherites) | V(ih) V(ih) | | ThreadBase | v v (v = uses) Pub Sub Then the next step is just to implement each function in the class diagram! You can do the same thing with each use case. Note broadcaster and Receiver are all threads inheriting public ThreadBase!!! I am very strong in writing multi thread code and OOP code! MyOrg1 High Availability Platform *HAP* MyOrg1 Software Architecture (OMC)--> SNMP agent (LT) --> RMI adaptor OAMP Framework EventManager AlarmManager UpgradeManager StatisticsManager ComponentFactoryManager CMI (to be inherited by)<--ApplicationComponent (The above stuff provides CMI) <--ProxyComponent-->PayloadBPPCard Component Framework InitializationService PAL PlatformDB Goahead Company Services(DB,DistributedMessage,failOver,SNMP) OS, Driver Hardware CMI=ComponentManagementInterface with virtual function to be inherited by user application Component *MyOrg1* MyOrg1 Hardware architecture: name=SPROC. 2N Redundant. Monted on ISB as single FRU, PowerPC, 366Mhz MPC750, 255 MB SDRAM, 1MB CacheMemory, 8MBBootFlash, 512SMBandDisk, 4 100Mb EthernetPorts. SPROC1 SPROC2 (manager) | \ / | ISB1 ISB2 CCA BPP DOC3 (CCA,BPP,DOC3 connected ISB1 and ISB2) *MyOrg1* Embedded real time software development: wrote code on NT machine, run on SPROC machine ==== *MyOrg1* All MyOrg1 software is a component inheriting a CMIBehavior abstract class: class CMIBehavior { public: CMIBehavior(); virtual ~CMIBehavior(); virtual bool onInitComponentSoftware( const ManagementState ) = 0 ; virtual void onGoActive( const ServiceName& instance, const ComponentName& switchFrom ) = 0 ; virtual void onGoStandby( const ComponentName& activeComponent, const ServiceName& activeInstance ) = 0 ; virtual void onAddActiveToStandby( const ComponentName& activeComponent, const ServiceName& activeInstance ) ; virtual void onDropActiveFromStandby( const ComponentName& activeComponent, const ServiceName& activeInstance ) ; virtual void onQuiesce() = 0 ; virtual void onReset( ResetType resetType ) = 0 ; virtual void onDeprovisionComponent() ; virtual void onActivateManager() ; virtual void onHeartbeat() ; void reportError(//for event const string& detectorEventName, AlarmType alarmType, ProbableCause probableCause, PerceivedSeverity perceivedSeverity, SpecificProblems specificProblems, ProposedRecoveryAction proposedRecoveryAction = ProposedRecoveryAction::NO_RECOVERY_ACTION, const DateAndTime& eventTime = DateAndTime(), const string& userDeviceName = ““, const string& additionalText = ““, const string& additionalInfo = ““ ) ; void setStatisticBehaviorMode( IntervalModeStatisticsBehavior& intervalMode ) ; void registerAsUpgradeableNode( bool codeSourceIndicator = false ) ; virtual bool onLoadAvailable( bool cleanLoadIndicator, const string& basePathname, const string& server = ““ ) ; void registerDeferUpgrade() ; virtual bool onDeferUpgrade() ; } ; ==== Software Structure and Modeling of Statistics Manager CMIBehavior ^ | StatisticsManager | \ \ RequestController \ Listener ---CMList--Node \ | | Mutex | | | | | Broadcaster | | | Subscriber / | | | | | \ | | V | | CMList Publisher | | ThreadBase Channel | Mutex | | Buffer | Semaphore | | | MessageQ | Channel XMLFileProcessor Semaphore V Buffer ThreadBase MessageQ ==== *MyOrg1* vxworks development use NFS mount, or CompactFlash disk (SandDisk with staging tool to stage images to SandDisk.) Target machine was originally HSP, NSP, then SPROC for cheaper price. How to set up target machine to boot up vxworks OS: 1) use serial port COM1 on NT to SPROC machine. Launch HyperTerminal, see PPC1-BUG> prompt. move jumper to 1-2. Then use commands such as: SET(to set time), NIOT(to configure client server IPs). Now do step 2) below first NIOP (to configure to use NTEboot.bin) to write to FLASH memory of SPROC to store bootloader. 2) Set up HCL Inetd to configure Tftpd to find bootloader (NETboot.bin on C:\HapImages\NETboot.bin) for SPROC to get bootloader. 3) move jumper to 2-3, then type in c to configure vxworks to auto-boot vxworks OS. Then type in @ to auto-boot vxworks 4) nfsmount to mount from NT directory to target directory }}}} End MyOrg1 ============================================================================= {{{{ Perl *How to create a perl module (a class in OOP term): #In ADB.pm file: #! /usr/bin/perl -w use strict ; package ADB; sub new { my $invocant = shift ; my $class = ref ( $invocant ) || $invocant ; my $self = { airgenDBName=>"airgen_cm_db", dbaccess=>"/usr/informix/bin/dbaccess", debugFlag=>0, m_rowCount=>-1, m_arrayRefFieldNames=>[], m_selectStatementExecuted=>0, @_ } ; if ( ! -f $self->{dbaccess} ) { print "$self->{dbaccess} does not exist, exiting....\n" ; exit ( 1 ) ; } if ( "@_" !~ /airgenDBName / ) { if ( defined ( $ENV{AIRGEN_DB_NAME} ) ) { $self->{airgenDBName} = $ENV{AIRGEN_DB_NAME} ; } } if ( defined ( $ENV{ADB_DEBUG} ) ) { $self->{debugFlag} = $ENV{ADB_DEBUG} ; } print "Your DB is $self->{airgenDBName}.\n" ; print "You can do export AIRGEN_DB_NAME= to use your own DB\n" ; print "You can do export ADB_DEBUG=1 to turn on debug flag\n" ; bless ($self, $class ) ; return $self ; } sub getSelectResults { my $self = shift ( @_ ) ; my $SQLStatement = shift ( @_ ) ; if ( $SQLStatement !~ /^\s*SELECT/i && $SQLStatement !~ /^\s*EXECUTE/i ) { print "\nOnly SELECT or EXECUTE statement can be used in this function!\n"; print "ADB is now exiting....\n" ; exit ( 1 ) ; } #.......... } #private function sub getLastCharacterIndexForEachFieldName { # note private function does not have my $self = shift(@_); my $string = shift ( @_ ) ; my $leadingSpaceCount = 0 ; } #.... 1 #last line for a module must be 1 ---------------------------- In try.pl to use ADB.pm: #! /usr/bin/perl -w use strict ; use ADB; my $adb = new ADB( airgenDBName=>"mirom45084_150011" ) ; my $SQLStatement = " select * from workspace_paramlog where seq_num=549593;"; my @allValueRecords = $adb->getSelectResults( $SQLStatement, __LINE__ ) ; #allValueRecords is an array itself, but it contains *references* to arrays!! #Note in code how to fill in the by using push like: pubsh (@{$allVauleRecords[$row0], 100); #use @ to promote reference to array @allValueRecords is like ( [100,2,3], [a, b, c], [200] ); for ( my $rowNum = 0 ; $rowNum < @allValueRecords ; $rowNum++ ) { print "\#$rowNum " ; for ( my $colNum = 0 ; $colNum < @{$allValueRecords[$rowNum]} ; $colNum++ ) { print ":${$allValueRecords[$rowNum]}[$colNum], " ; } print "\n" ; } }}}} End Perl ============================================================================= {{{{ SQL * ALTER TABLE isg add voice_reception_method smallint default 0 not null; table_exists=`echo "select count(*) from systables where systables.tabname = '$1';"| $DBACCESS $DB | /usr/bin/grep -v 'count'` * SELECT count(constrname) FROM sysconstraints WHERE tabid = ( SELECT tabid * FROM systables WHERE tabname="$1" ) AND constrname = "$2" AND * constrtype="P"; * CREATE TABLE WARD ( WORKSPACE_ID INTEGER NOT NULL, iVPU_INST INTEGER NOT NULL, HN_TOS SMALLINT DEFAULT 0 NOT NULL, HN_IP_ADDRESS CHAR ( 15 ) NOT NULL, HN_DEV_ID SMALLINT NOT NULL, PRIMARY KEY (WORKSPACE_ID, iVPU_INST) CONSTRAINT PK_WARD, UNIQUE (WORKSPACE_ID, HN_DEV_ID) CONSTRAINT TC_WARD ); * ALTER TABLE ward ADD CONSTRAINT FOREIGN KEY (workspace_id, ivpu_inst) * REFERENCES ivpu (workspace_id, ivpu_inst) CONSTRAINT fk_ward_ivpu; *Stored procedure -- in fr_rep.sp.sql: CREATE PROCEDURE cleanup_fr_util ( ) ON EXCEPTION IN (-674) -- procedure does not exist -- keep going if procedure does not already exist END EXCEPTION WITH RESUME; -- Drop all procedure DROP PROCEDURE un_config_sites ; END PROCEDURE; EXECUTE PROCEDURE cleanup_fr_util(); DROP PROCEDURE cleanup_fr_util; CREATE PROCEDURE un_config_sites ( p_wsid INTEGER ) RETURNING CHAR ( 20 ), SMALLINT, SMALLINT ; DEFINE mystr_mso_name CHAR ( 20 ) ; DEFINE myint_mso_id INTEGER ; DEFINE mysi_unconfigsites SMALLINT ; DEFINE mysi_configsites SMALLINT ; FOREACH SELECT mso.mso_name, mso.mso_id INTO mystr_mso_name, myint_mso_id FROM mso WHERE mso.workspace_id = p_wsid SELECT count(*) INTO mysi_configsites FROM ne ne_acg, acg WHERE ne_acg.workspace_id = p_wsid AND ne_acg.ne_type = 0 AND ne_acg.mso_id = myint_mso_id AND acg.workspace_id = p_wsid AND acg.acg_inst = ne_acg.ne_inst AND acg.preconfig_flag = 0 AND acg.ivpu_inst IS NOT NULL ; SELECT count(*) INTO mysi_unconfigsites FROM ne ne_acg, acg WHERE ne_acg.workspace_id = p_wsid AND ne_acg.ne_type = 0 AND ne_acg.mso_id = myint_mso_id AND acg.workspace_id = p_wsid AND acg.acg_inst = ne_acg.ne_inst AND acg.preconfig_flag = 0 AND acg.ivpu_inst IS NULL ; RETURN mystr_mso_name, mysi_configsites, mysi_unconfigsites WITH RESUME ; END FOREACH ; END PROCEDURE; *ec code: //uSQL_util.ec EXEC SQL include sqlca; EXEC SQL begin declare section; EXEC SQL include airgen_types.h; EXEC SQL end declare section; int fr_IIR (GUISQL_Fr *mem_fr_record) { EXEC SQL begin declare section; GUISQL_Fr *fr_record; int iPath_null, iSecgid_null ; EXEC SQL end declare section; fr_record = mem_fr_record; EXEC SQL execute procedure fr_IIR( :fr_record->szEbtsName, :fr_record->szIvpuName) into :fr_record->szPath : iPath_null, /* acg_name */ :fr_record->iSecgid : iSecgid_null; if ( iPath_null == -1 ) //get nothing from db, but no error! { strcpy ( fr_record->szPath, "" ) ; } if ( iSecgid_null == -1 ) { fr_record->iSecgid = -1 ; } if (SQLCODE != 0){ printf("SQLCODE=%d", SQLCODE) ; } return SQLCODE; } ---- EXEC SQL begin declare section; char select_from_type[QUERY_LENGTH]; EXEC SQL end declare section; EXEC SQL database :airgen_db_name; EXEC SQL begin work; sprintf (select_from_type, "SELECT ne1.ne_type .... " ) ; //a SQL statement EXEC SQL PREPARE s_from_type FROM :select_from_type; RETURNIFERROR; EXEC SQL EXECUTE s_from_type INTO :from_type; IFSQLERR_LOG_SET(sqlcode); EXEC SQL FREE s_from_type; IFSQLERR_LOG_SET(sqlcode); RETURN_IF(sqlcode != 0); if ( from_type == 2 ) { .... } //Now use cursor: sprintf(select_cell_sector, "SELECT cell.sector_id...." ) ; EXEC SQL prepare s_cell_sector from :select_cell_sector; RETURNIFERROR; EXEC SQL declare cell_sector cursor for s_cell_sector; IFSQLERR_LOG_SET(sqlcode); if (sqlcode != 0) { EXEC SQL FREE s_cell_sector; IFSQLERR_LOG_SET(sqlcode); EXEC SQL rollback work; return FALSE; } no_cell_sector = 0; EXEC SQL open cell_sector; IFSQLERR_LOG_SET(sqlcode); if (sqlcode != 0) { EXEC SQL FREE cell_sector; IFSQLERR_LOG_SET(sqlcode); EXEC SQL FREE s_cell_sector; IFSQLERR_LOG_SET(sqlcode); EXEC SQL rollback work; return FALSE; } EXEC SQL fetch cell_sector into :cell_sector_id; if (SQLCODE == 100) //not a row found { strcpy(sector_id[no_cell_sector], ""); } else { while (SQLCODE == 0) { //.... EXEC SQL fetch cell_sector into $cell_sector_id; if( SQLCODE == 0) { strcpy(sector_id[no_cell_sector], cell_sector_id); no_cell_sector++; } } } if (SQLCODE != SQLNOTFOUND) IFSQLERR_LOG_SET(sqlcode); EXEC SQL close cell_sector; IFSQLERR_LOG_SET(sqlcode); EXEC SQL FREE cell_sector; IFSQLERR_LOG_SET(sqlcode); EXEC SQL FREE s_cell_sector; IFSQLERR_LOG_SET(sqlcode); RETURN_IF(sqlcode != 0); .... EXEC SQL commit work; ---- TRIGGER -- assume mytalbe has nodeid column CREATE TRIGGER mytrigger UPDATE on mytable REFERENCING new AS n old AS o FOR EACH ROW WHEN ( ( n.nodeid is null and o.node is not null) or (n.nodeid is not null and o.nodeid is null ) or (n.nodeid!=o.nodeid ) ) (EXECUTE PROCEDURE mystoredprocedure(n.nodeid, o.nodeid ) ; ---- *OMC* MoveSite class model: UIComponent //manage widgets tree virtual manage() virtual unmanage() virtual widgetDestroyed() protected: Widget _w ; //set in derived class ^ | MoveSiteForm m_wgMoveSiteForm m_wgLabel m_wgTextField m_pAcgName virtual void applyButtonActivateCB(...), and other callBack(CB) ^ <> <> <> / | | \ / |n |n \ MoveSiteFormDerived Widget DropDownWindow Others... *OMC* Broker of Airgen_CM_DB: Architecture(portion only, class model, broker has 300KLOC!) OBWind::postusr__mail_drop calls do_request calls through polymorphism of OBForm::db_insert OBForm virtual db_insert ^ ^ | | OBFldForm__SimpleFieldForm OBTblForm__TableForm db_insert db_insert calls calls OBForm execute_change_sql which interates through a dictionary of [sql_op(eg.insert etc), listOfSQLObjects] by calling through polymorphism of OBSQL::obsql__execute() OBSQL pure virtual obsql__execute()=0 ^ ^ ^ | | | OBSQLChg__SQLChange OBSQLSel__SQLSelect OBSQLBlob__SQLBlobUpdate obsql__execute obsql__execute obsql__execute which calls build_for_execute (to build stored procedures) then calls ::dsqlchgf__change_forced in dsqlchgf.ec ==== *OMC* Airgen_CM_GUI: Architecture(class model) Evntrcvr__EventReceiver Postusr ^ ^ | | FormWin(implements postusr__mail_drop in order receive data from object broker) ^ | UICW__ConfigWindow *OMC* Airgen_CM_GUI is drawn in Teleuse which defines GUI resource file and GUI change events and rules for handling the GUI events }}}} End SQL ============================================================================= {{{{ Linux *Linux* Component to boot up a target machine: boot.msg ldlinux.sys (boot loader for RAM disk and kernel) initrd.img <-specify optons--syslinux.cig-specify/uncompress kernel->vmlinuz (RAM fileSystem) | (kernel) | BIOS read syslinux.cig execute it. ldlinux.sys/syslinu.cfg vmlinuz initrd.img(will in RAM) BIOS Syslinux CompressedKernel CompressedFileSystem Init |- read- | | |-read/uncompress/execute--| | | |-read/uncompress/mount/-| | | | | |-run Init-----------------------------| | | | |-read /etc/inittab------| | |-execute sysinit line+ |---------------------| |execute /etc/rs.sysinit to start app. The whole FileSystem after compression is in memory!!! Not in floppy disk anymore. Syslinux is boot image loader ( or boot loader) *Linux* A device dirver must have a major number. Kernel only knows the major number of the driver. Driver operates on device file, device file alson is known to application. A device file must have a major number and a name. Device file lives in /dev directory. Device file is not data file, must use mknode to make it. *Linux* Files under /etc directory are for configuration of system after it starts, file example: /etc/inittab (to start shell, web server and other application) /etc/hosts ( names resolutions to IPs) /etc/nsswitch.conf (name servers order info, for gethostbyname) /etc/rs.sysinit (use insmod to insert driver module to system) *Linux* Files under /lib are device driver files *Linux* Shell commands: cut, grep, xargs, fsck, df, read, while, whoami, export, basename, date, echo, 2>&1, 2>/dev/null, tty, sed, ls, rm, tar, case, *Linux* TCP/IP: ipconfig attribute ping: steps involved 1) resolve hostname to ip using /etc/hosts file, 2) use ARP broadcast to get etherned address of target ip, then send a frame to ethernet address ping uses ICMP protocol. arp -a: a command to show ethernet add and ip address mapping *Linux* Get a list of dynamically linked library: ldd $(whence MoveSite) Dynamic library ends with .so, static linked library ends with .a *Linux* Before compile vmlinuz, use make configuration menu to configure, then make dep, make zImage, make modules, make module_install *Linux* file, strip to strip down size of executable }}}} End Linux ============================================================================= {{{{ Thread *pthread* calling sequence: pthread_attr_init(pthread_attr_t* attr_p); pthread_attr_setdetachstate(attr_p, CONST) pthread_attr_setschedparam(attr_p, (struct sched_param*)priority_p) pthread_create(&tid,attr_p, callBackFuntion, my_data_p); pthread_attr_destroy(attr_p) ---- pthread_exit(&status) //to terminate an attached thread pthread_detach(&status) //to terminate an detached thread pthread_join(tid, &status) //to wait for termination of an attached thread pthread_sigmask(SIG_CONST,sigset_p, old_sigset_p) pthread_kill(tid,SIG_CONST) sched_yield(&status) }}}} End Thread {{{{ XML *XML* Example XML file myquote.xml: #xjiNote: this is processing line #xjiNote: this is comment #xjiNote: DTD for quotation root 742-14509 windowButton .22 Mike O'Neil #xjiNote:' is ' goofy XML]]> #xjiNote:CData can have any characters ---- So quotation.dtd is like: #xjiNote: optional *XML* DTD(Document Type Definition) *XML* DTD limitation: can not validate data type and range. So we will use XML schema. The most important thing about XML schema is that it specify data type for element and attribute. *XML* xml file using XML schema: In file: myquote.xml 742-14509 windowbutton .22 In file: quotation.xsd: #xji must rootElement! *XML* have five special characters, which must be written as &; & & < < > > " " ' ' *XML* Regarding data being stored in XML file, using attribute is the same as using element. *XML* DOM is a programming language neutral interface for programming language to develop APIs to create element, retrieve attribute of element, create new XML file etc. Everything in xml file can be represented as a DOM node, perl provides XML::DOM module to parse xml document. example code: use XML::DOM ; my $parser = new XML::DOM::Parser ; my $doc = $parser->parsefile($myXmlFile) ; my $nodeList = $doc->getElementByTagName('partName') ; my data = $nodeList->item(0)->getFirstChild()->getNodeValue(); print "part name is \t$data\n" ; my $root = $doc->getDocumentElement(); my $quantity = $root->getAttribute('releaseQuantity') ; print "release quantity is\t$quantity\n" ; $doc->dispose(); }}}} End XML ============================================================================= {{{{ Other *IP* TCP Header SourcePort DestinationPort sequenceNumber AcknowledgeNumber TCPHeaderLength URGbit, ACKbit,PSHbit, RSTbit, SYNbit FINbit WindowSize Checksum UrgentPointer Options Payload(Data) *IP* IP Header: version IHL TypeOfService TotalLength IdentificationNumber DF MF FragmentOffset <-all this line for fragmentation TimeToLive Protocol(TCP/UDP) HeaderChecksum SourceAddress DestinationAddress Options *IP Frame Format(DataLinkLayer) Flag01111110 MacAdd ControlByt PacketProtocol Payload Checksum Flag01111110 *IP* TCP/IP over ATM Application TCP/UDP IP ATM DataLinkLayer PhysicalLayer *Socket* API callingSequence(TCP) ServerSocket ClientSocket socket socket (to get sid) bind listen connect (to server's address) accept send or recv send or recv shutdown shutdown close close *Socket* sockfd=Socket(AF_INET, SOCK_DGRAM,0) *Socket* API callingSequence(UCP) Both Server and Client have following API sequence: socket bind sendto recvfrom close *Tramsmit: 890-915 MHz, 125 carriers x 200 KHz at 270 kbps. Each frame: 0.577ms/timeslot=57x2 bit data. Each channel: 8Frames=8 slots of time = 8*0.577=4.615ms. 8x57x2 bit data. *Receive: 935-960 MHz *Phone->EBTS->BSC->MSC Mobile Switch Center(with HLR and VLR)-> SwitchCenter->(E1 line) PSTN 1) Phone on -> 2) Scan to find its location->3) Registration ->4)RequestChannel->5)Authentication->6)EEstatblishConnection-> 7)MonitorSignalStrength->8)Handover(if necessary) by MSC and BSC 3,4, and 5 are layer 3 as in OSI 5. CM:callControlManagement -- CM 4. MM:mobilityManagement -- MM 3. RR:radioResource -- MTP3,SCCP:singalingConnectionCtrl 2. LAPDm:linkAccessProcedureDataLink -- MTP2 1. GSMRF:GSMRadioFrequence -- MTP1:messageTransferPart1 Cellphone 0.8~8W, baseStation ~300W. Speech->GSMCoder->ChannelCoding->Interleaving->Ciphering->Modulatoin->Transmit. OSI: Physical->DataLink->Network->Transport->Session->Presentation->Applictn. UNIX: HostToNetwork->IP->TCP->Applictn. *Wireless Broadband access* To reduce interference (on physical layer): 1. Array of Sectorized antennas: 8 antennas each with 45 degree spread, so we have directional high power transmission between point(node) and point(node) of base station. 1a. Multiple adaptive antennas system (AAS) 2. Variable Modulation to get different bps speed to select the optimal types: Modulatoins scheme: Quarature Amplitude Modulatoin(QAM), Phase shifting key of modulation to get best BER. 3. FEC(Forward error correction), automatic repeat request(ARQ) 4. Time synchronization using GPS with Time Division Duplex protocol to control or schedule transmission between nodes. 5. Mesh Topology: because of 1, 2, and 3 above, mesh topoloy is possible in wireless broadband access with low interference. 6. Power control 6. NLOS 2-11 GHz spectrum. *MAC* Frame format: MACFrameHeader(with CID) + payload(PDU) + CRC (circular redundancy check,or chksm) Because WiMAX is connection-oriented (a permenant connection between BTS and subscriber station) so no need for MAC address in PDU in MAC layer what we need is just CID connection id. So in MACFrameHeader we have CID, no source or destination MAC FEC block = MAC (PDU with CID) + CRC Preamble + FEC blocks The lowest of MAC layer is privacy sublayer(data encryption scheme + key management), X.509 digital certificates is very strong privit and public key. Qos=bandwith + throughput + latency + jitter(delay variation) *WiMAX* Mac layer Service Specific Convergence subLayer(classification of higherLayer data from ATM, IP,etc) MAC Common part Sublayer(downlink+uplink, duplex, using TDD with differetn time slots. FDD can also be used for downlink or uplink) Privacy Sublayer *WiMAX* Physical layer Physical layer (2 - 11GHz, nonlightOfSight(NLOS), O(orthogonal)FDMA ) only OFDMA: divide channel into many sub-channels which are multiplexed into one fat channel, these subchannels are orthogonal to each other. *WiMAX CoreNetwork<-->BS(BaseStation)<1--n>SubscriberStation(SSor CPE)<1--n>TE(laptop) It is called last mile access from SS to BS. *WiMAX* WiMAX is MAN, not LAN. *WiMAX* SS(SubscriberStation) initialization: 1. scan for downlink channel and synchronization with BaseStation(BS) 2. Obtain transmit pamaters 3. Perform ranging between SS and BS to find the distance and power level. 4. Negotiate basic capabilities supported, 5. Authorize SS and key exchange between SS and BS. 6. Registration of capabilities 7. Establish IP connectivity via DHCP, BS provisioning SS with configuration file via TFTP: 8. Establish time of day 9. Transfer operational parameters 10. Set up connections(CID). }}}} End Other