因项目需要,对QualNet仿真中节点间收发包行为进行了仔细研究,并不断添加一些输出以验证思路。应该说,大致是正确的,可能有些细节研究还不够透彻。对一般的应用协议开发已经够用了,如果想制作一个完整的组件添加进去,还需进一步深入。
以下以发送端节点向接收端节点发送应用层消息为例,介绍QualNet收发包过程。
1. 发送端
1.1 应用层
创建传输层UDP协议消息MSG_TRANSPORT_FromAppSend,添加了信息字段AppToUdpSend,发送(即调度传输层处理该消息)。函数见~/main/app_util.cpp
void APP_UdpSendNewHeaderData(
Node *node,
AppType appType,
NodeAddress sourceAddr,
short sourcePort,
NodeAddress destAddr,
char *header,
int headerSize,
char *payload,
int payloadSize,
clocktype delay,
TraceProtocolType traceProtocol)
{
Message *msg;
AppToUdpSend *info;
msg = MESSAGE_Alloc(
node,
TRANSPORT_LAYER,
TransportProtocol_UDP,
MSG_TRANSPORT_FromAppSend);
MESSAGE_PacketAlloc(node, msg, payloadSize, traceProtocol);
memcpy(MESSAGE_ReturnPacket(msg), payload, payloadSize);
MESSAGE_AddHeader(node, msg, headerSize, traceProtocol);
memcpy(MESSAGE_ReturnPacket(msg), header, headerSize);
MESSAGE_InfoAlloc(node, msg, sizeof(AppToUdpSend));
info = (AppToUdpSend *) MESSAGE_ReturnInfo(msg);
SetIPv4AddressInfo(&info->sourceAddr, sourceAddr);
info->sourcePort = sourcePort;
SetIPv4AddressInfo(&info->destAddr, destAddr);
info->destPort = (short) appType;
info->priority = APP_DEFAULT_TOS;
info->outgoingInterface = ANY_INTERFACE;
info->ttl = IPDEFTTL;
MESSAGE_Send(node, msg, delay);
}
1.2 传输层
应用层调度了传输层消息,由~/main/transport.cpp中消息处理函数TRANSPORT_ProcessEvent处理。如下所示,根据消息的协议类型选择具体协议处理,条理清晰。
void TRANSPORT_ProcessEvent(Node * node, Message * msg)
{
switch (MESSAGE_GetProtocol(msg))
{
case TransportProtocol_UDP:
{
TransportUdpLayer(node, msg);
break;
}
case TransportProtocol_TCP:
{
TransportTcpLayer(node, msg);
break;
}
case TransportProtocol_RSVP:
......
}
}
UDP消息处理函数TransportUdpLayer如下所示,再根据消息类型选择具体处理方式。
void TransportUdpLayer(Node *node, Message *msg)
{
switch (msg->eventType)
{
case MSG_TRANSPORT_FromNetwork:
{
TransportUdpSendToApp(node, msg);
break;
}
case MSG_TRANSPORT_FromAppSend:
{
TransportUdpSendToNetwork(node, msg);
break;
}
default:
assert(FALSE);
abort();
}
}
传输层向网络层发送数据,消息类型MSG_TRANSPORT_FromAppSend,调用函数TransportUdpSendToNetwork。在函数中添加了UDP首部TransportUdpHeader,调用网络层函数接收数据包。如下所示。
void TransportUdpSendToNetwork(Node *node, Message *msg)
{
TransportDataUdp *udp = (TransportDataUdp *) node->transportData.udp;
TransportUdpHeader *udpHdr;
AppToUdpSend *info;
unsigned char protocol = IPPROTO_UDP;
info = (AppToUdpSend *) MESSAGE_ReturnInfo(msg);
MESSAGE_AddHeader(node, msg, sizeof(TransportUdpHeader), TRACE_UDP);
udpHdr = (TransportUdpHeader *) msg->packet;
udpHdr->sourcePort = info->sourcePort;
udpHdr->destPort = info->destPort;
udpHdr->length = (unsigned short) MESSAGE_ReturnPacketSize(msg);
udpHdr->checksum = 0;
//调用网络层函数接收数据
NetworkIpReceivePacketFromTransportLayer(
node,
msg,
info->sourceAddr,
info->destAddr,
info->outgoingInterface,
info->priority,
pr