#include <UDPSocket.h>
UDPSocket chooses and remembers the sockId for you, assembles and sends command packets (such as OPEN_ACTIVE, OPEN_PASSIVE, CLOSE, ABORT, etc.) to TCP, and can also help you deal with packets and notification messages arriving from TCP.
A session which opens a connection from local port 1000 to 10.0.0.2:2000, sends 16K of data and closes the connection may be as simple as this (the code can be placed in your handleMessage() or activity()):
UDPSocket socket; socket.connect(IPvXAddress("10.0.0.2"), 2000);
msg = new cMessage("data1"); msg->setByteLength(16*1024); // 16K socket.send(msg);
socket.close();
Dealing with packets and notification messages coming from TCP is somewhat more cumbersome. Basically you have two choices: you either process those messages yourself, or let UDPSocket do part of the job. For the latter, you give UDPSocket a callback object on which it'll invoke the appropriate member functions: socketEstablished(), socketDataArrived(), socketFailure(), socketPeerClosed(), etc (these are methods of UDPSocket::CallbackInterface)., The callback object can be your simple module class too.
This code skeleton example shows how to set up a UDPSocket to use the module itself as callback object:
class MyModule : public cSimpleModule, public UDPSocket::CallbackInterface { UDPSocket socket; virtual void socketDataArrived(int sockId, void *yourPtr, cMessage *msg, bool urgent); virtual void socketFailure(int sockId, void *yourPtr, int code); ... };
void MyModule::initialize() { socket.setCallbackObject(this,NULL); }
void MyModule::handleMessage(cMessage *msg) { if (socket.belongsToSocket(msg)) socket.processMessage(msg); else ... }
void MyModule::socketDatagramArrived(int, void *, cMessage *msg, UDPControlInfo *ctrl) { ev << "Received UDP packet, " << msg->byteLength() << " bytes\\n"; delete msg; }
void MyModule::socketPeerClosed(int, void *, int code) { ev << "Socket peer closed!\\n"; }
If you need to manage a large number of sockets, the UDPSocketMap class may be useful.
Handling of messages arriving from UDP | |
bool | belongsToSocket (cMessage *msg) |
void | setCallbackObject (CallbackInterface *cb, void *yourPtr=NULL) |
void | processMessage (cMessage *msg) |
static bool | belongsToAnyUDPSocket (cMessage *msg) |
Public Types | |
enum | State { NOT_BOUND, BOUND } |
Public Member Functions | |
UDPSocket () | |
~UDPSocket () | |
int | socketId () const |
void | setUserId (int userId) |
int | userId () const |
int | state () |
Getter functions | |
IPvXAddress | localAddress () |
int | localPort () |
Opening and closing connections, sending data | |
void | setOutputGate (cGate *toUdp) |
void | bind (int localPort) |
void | bind (IPvXAddress localAddr, int localPort) |
void | connect (IPvXAddress remoteAddr, int remotePort) |
void | setMulticastInterface (int interfaceId) |
int | multicastInterface () const |
void | sendTo (cMessage *msg, IPvXAddress destAddr, int destPort) |
void | send (cMessage *msg) |
void | close () |
Static Public Member Functions | |
static const char * | stateName (int state) |
static int | generateSocketId () |
Protected Member Functions | |
void | sendToUDP (cMessage *msg) |
Protected Attributes | |
int | sockId |
int | usrId |
int | sockstate |
IPvXAddress | localAddr |
int | localPrt |
IPvXAddress | remoteAddr |
int | remotePrt |
int | mcastIfaceId |
CallbackInterface * | cb |
void * | yourPtr |
cGate * | gateToUdp |
Classes | |
class | CallbackInterface |
|
|
|
Constructor. The socketId() method returns a valid Id right after constructor call. 00023 { 00024 // don't allow user-specified sockIds because they may conflict with 00025 // automatically assigned ones. 00026 sockId = generateSocketId(); 00027 usrId = -1; 00028 sockstate = NOT_BOUND; 00029 00030 localPrt = remotePrt = 0; 00031 mcastIfaceId = -1; 00032 cb = NULL; 00033 yourPtr = NULL; 00034 00035 gateToUdp = NULL; 00036 }
|
|
Destructor 00149 {}
|
|
Returns true if the message belongs to any UDPSocket instance. (This basically checks if the message has an UDPControlInfo attached to it as controlInfo().) 00175 {
00176 return dynamic_cast<UDPControlInfo *>(msg->controlInfo());
00177 }
|
|
Returns true if the message belongs to this socket instance (message has a UDPControlInfo as controlInfo(), and the sockId in it matches that of the socket.) 00169 { 00170 return dynamic_cast<UDPControlInfo *>(msg->controlInfo()) && 00171 ((UDPControlInfo *)(msg->controlInfo()))->sockId()==sockId; 00172 }
|
|
Bind the socket to a local port number and IP address (useful with multi-homing or multicast addresses). Use port=0 for an ephemeral port. 00092 { 00093 if (sockstate!=NOT_BOUND) 00094 opp_error("UDPSocket::bind(): socket already bound"); 00095 if (lPort<=0 || lPort>65535) 00096 opp_error("UDPSocket::bind(): invalid port number %d", lPort); 00097 00098 localAddr = lAddr; 00099 localPrt = lPort; 00100 00101 UDPControlInfo *ctrl = new UDPControlInfo(); 00102 ctrl->setSockId(sockId); 00103 ctrl->setUserId(usrId); 00104 ctrl->setSrcAddr(localAddr); 00105 ctrl->setSrcPort(localPrt); 00106 cMessage *msg = new cMessage("BIND", UDP_C_BIND); 00107 msg->setControlInfo(ctrl); 00108 sendToUDP(msg); 00109 00110 sockstate = BOUND; 00111 }
|
|
Bind the socket to a local port number. Use port=0 for ephemeral port. 00072 { 00073 if (sockstate!=NOT_BOUND) 00074 opp_error("UDPSocket::bind(): socket already bound"); 00075 if (lPort<=0 || lPort>65535) 00076 opp_error("UDPSocket::bind(): invalid port number %d", lPort); 00077 00078 localPrt = lPort; 00079 00080 UDPControlInfo *ctrl = new UDPControlInfo(); 00081 ctrl->setSockId(sockId); 00082 ctrl->setUserId(usrId); 00083 ctrl->setSrcPort(localPrt); 00084 cMessage *msg = new cMessage("BIND", UDP_C_BIND); 00085 msg->setControlInfo(ctrl); 00086 sendToUDP(msg); 00087 00088 sockstate = BOUND; 00089 }
|
|
Unbinds the socket. There is no need for renewSocket() as with TCPSocket. 00156 { 00157 if (sockstate!=BOUND) 00158 return; 00159 00160 cMessage *msg = new cMessage("UNBIND", UDP_C_UNBIND); 00161 UDPControlInfo *ctrl = new UDPControlInfo(); 00162 ctrl->setSockId(sockId); 00163 msg->setControlInfo(ctrl); 00164 sendToUDP(msg); 00165 sockstate = NOT_BOUND; 00166 }
|
|
Connects to a remote UDP socket. This has two effects: (1) this socket will only receive packets from specified address/port, and (2) you can use send() (as opposed to sendTo()) to send packets. 00114 { 00115 if (sockstate!=BOUND) 00116 opp_error( "UDPSocket::connect(): socket must be bound before connect() can be called"); 00117 if (addr.isUnspecified()) 00118 opp_error("UDPSocket::connect(): unspecified remote address"); 00119 if (port<=0 || port>65535) 00120 opp_error("UDPSocket::connect(): invalid remote port number %d", port); 00121 00122 remoteAddr = addr; 00123 remotePrt = port; 00124 00125 UDPControlInfo *ctrl = new UDPControlInfo(); 00126 ctrl->setSockId(sockId); 00127 ctrl->setDestAddr(remoteAddr); 00128 ctrl->setDestPort(remotePrt); 00129 cMessage *msg = new cMessage("CONNECT", UDP_C_CONNECT); 00130 msg->setControlInfo(ctrl); 00131 sendToUDP(msg); 00132 }
|
|
Generates a new socket id. 00052 {
00053 return ev.getUniqueNumber();
00054 }
|
|
00186 {return localAddr;}
|
|
00187 {return localPrt;}
|
|
Returns the output interface for sending multicast packets. 00227 {return mcastIfaceId;}
|
|
Examines the message (which should have arrived from UDP), and if there is a callback object installed (see setCallbackObject(), class CallbackInterface), dispatches to the appropriate method of it with the same yourPtr that you gave in the setCallbackObject() call. IMPORTANT: for performance reasons, this method doesn't check that the message belongs to this socket, i.e. belongsToSocket(msg) would return true! 00186 { 00187 UDPControlInfo *ctrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo()); 00188 ASSERT(ctrl->sockId()==sockId); 00189 00190 switch (msg->kind()) 00191 { 00192 case UDP_I_DATA: 00193 if (cb) 00194 cb->socketDatagramArrived(sockId, yourPtr, msg, ctrl); 00195 else { 00196 delete msg; 00197 delete ctrl; 00198 } 00199 break; 00200 case UDP_I_ERROR: 00201 sockstate = NOT_BOUND; 00202 delete msg; 00203 if (cb) 00204 cb->socketPeerClosed(sockId, yourPtr); 00205 break; 00206 default: 00207 opp_error("UDPSocket: invalid msg kind %d, one of the UDP_I_xxx constants expected", msg->kind()); 00208 } 00209 }
|
|
Sends a data packet to the address and port specified previously in a connect() call. 00149 { 00150 if (remoteAddr.isUnspecified() || remotePrt==0) 00151 opp_error("UDPSocket::send(): must call connect() before using send()"); 00152 sendTo(msg, remoteAddr, remotePrt); 00153 }
|
|
Sends a data packet to the given address and port. 00135 { 00136 msg->setKind(UDP_C_DATA); 00137 UDPControlInfo *ctrl = new UDPControlInfo(); 00138 ctrl->setSockId(sockId); 00139 ctrl->setSrcAddr(localAddr); 00140 ctrl->setSrcPort(localPrt); 00141 ctrl->setDestAddr(destAddr); 00142 ctrl->setDestPort(destPort); 00143 ctrl->setInterfaceId(mcastIfaceId); 00144 msg->setControlInfo(ctrl); 00145 sendToUDP(msg); 00146 }
|
|
00057 { 00058 if (!gateToUdp) 00059 opp_error("UDPSocket: setOutputGate() must be invoked before socket can be used"); 00060 00061 check_and_cast<cSimpleModule *>(gateToUdp->ownerModule())->send(msg, gateToUdp); 00062 }
|
|
Sets a callback object, to be used with processMessage(). This callback object may be your simple module itself (if it multiply inherits from CallbackInterface too, that is you declared it as class MyAppModule : public cSimpleModule, public UDPSocket::CallbackInterfaceand redefined the necessary virtual functions; or you may use dedicated class (and objects) for this purpose. UDPSocket doesn't delete the callback object in the destructor or on any other occasion. YourPtr is an optional pointer. It may contain any value you wish -- UDPSocket will not look at it or do anything with it except passing it back to you in the CallbackInterface calls. You may find it useful if you maintain additional per-connection information: in that case you don't have to look it up by sockId in the callbacks, you can have it passed to you as yourPtr.
|
|
Set the output interface for sending multicast packets (like the Unix IP_MULTICAST_IF socket option). The argument is the interface's Id in InterfaceTable. 00222 {mcastIfaceId = interfaceId;}
|
|
Sets the gate on which to send to UDP. Must be invoked before socket can be used. Example: 00197 {gateToUdp = toUdp;}
|
|
Sets userId to an arbitrary value. (This value will be sent back to us by UDP in UDPControlInfo if we receive a packet on this socket.) 00065 { 00066 if (sockstate!=NOT_BOUND) 00067 opp_error("UDPSocket::setUserId(): cannot change userId after socket is bound"); 00068 usrId = userId; 00069 }
|
|
Returns the internal socket Id. 00154 {return sockId;}
|
|
Returns the socket state, one of NOT_BOUND, BOUND, etc. Messages received from UDP must be routed through processMessage() in order to keep socket state up-to-date. 00172 {return sockstate;}
|
|
Returns name of socket state code returned by state(). 00039 { 00040 #define CASE(x) case x: s=#x; break 00041 const char *s = "unknown"; 00042 switch (state) 00043 { 00044 CASE(NOT_BOUND); 00045 CASE(BOUND); 00046 } 00047 return s; 00048 #undef CASE 00049 }
|
|
Returns the userId. 00165 {return usrId;}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|