概述
整个流程大概是:
-
do_state(ptp_master状态)
-
issueAnnounce
- netSendGeneral
-
handle
- netRecvGeneral
-
ssize_t netSendGeneral(Octet * buf, UInteger16 length, NetPath * netPath, const const RunTimeOpts *rtOpts, Integer32 destinationAddress) { ssize_t ret; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(PTP_GENERAL_PORT); #ifdef PTPD_PCAP if ((netPath->pcapGeneral != NULL) && (rtOpts->transport == IEEE_802_3)) { ret = netSendPcapEther(buf, length, &netPath->etherDest, (struct ether_addr *)netPath->interfaceID, netPath->pcapGeneral); if (ret <= 0) DBG("Error sending ether multicast general messagen"); else { netPath->sentPackets++; netPath->sentPacketsTotal++; } } else { #endif if(destinationAddress) { addr.sin_addr.s_addr = destinationAddress; /* * This function is used for PTP only anyway... * If we're sending to a unicast address, set the UNICAST flag. */ *(char *)(buf + 6) |= PTP_UNICAST; ret = sendto(netPath->generalSock, buf, length, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if (ret <= 0) DBG("Error sending unicast general messagen"); else { netPath->sentPackets++; netPath->sentPacketsTotal++; } } else { addr.sin_addr.s_addr = netPath->multicastAddr; /* Is TTL OK? */ if(netPath->ttlGeneral != rtOpts->ttl) { /* Try restoring TTL */ if (netSetMulticastTTL(netPath->generalSock,rtOpts->ttl)) { netPath->ttlGeneral = rtOpts->ttl; } } ret = sendto(netPath->generalSock, buf, length, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if (ret <= 0) DBG("Error sending multicast general messagen"); else { netPath->sentPackets++; netPath->sentPacketsTotal++; } } #ifdef PTPD_PCAP } #endif return ret; }
- 上面是发送网络包的源码,其中ret是为了配合接收packet而返回的文件描述字(符合Linux一切皆是文件的理念)。
- 其中PTPD_PCAP那部分不重要,貌似没有作用,暂不了解。
- 有destinationAddress就unicast,没有multicast。
ssize_t netRecvGeneral(Octet * buf, NetPath * netPath) { ssize_t ret = 0; struct sockaddr_in from_addr; #ifdef PTPD_PCAP struct pcap_pkthdr *pkt_header; const u_char *pkt_data; #endif socklen_t from_addr_len = sizeof(from_addr); netPath->lastSourceAddr = 0; #ifdef PTPD_PCAP if (netPath->pcapGeneral == NULL) { #endif ret=recvfrom(netPath->generalSock, buf, PACKET_SIZE, MSG_DONTWAIT, (struct sockaddr*)&from_addr, &from_addr_len); netPath->lastSourceAddr = from_addr.sin_addr.s_addr; /* do not report "from self" */ if(!netPath->lastSourceAddr || (netPath->lastSourceAddr != netPath->interfaceAddr.s_addr)) { netPath->receivedPackets++; } netPath->receivedPacketsTotal++; return ret; #ifdef PTPD_PCAP } #endif #ifdef PTPD_PCAP else { /* Using PCAP */ /* Discard packet on socket */ if (netPath->generalSock >= 0) recv(netPath->generalSock, buf, PACKET_SIZE, MSG_DONTWAIT); if (( ret = pcap_next_ex(netPath->pcapGeneral, &pkt_header, &pkt_data)) < 1) { if (ret < 0) DBGV("netRecvGeneral: pcap_next_ex failed %d %sn", ret, pcap_geterr(netPath->pcapGeneral)); return 0; } /* Make sure this is IP (could dot1q get here?) */ if( ntohs(*(u_short *)(pkt_data + 12)) != ETHERTYPE_IP) { if( ntohs(*(u_short *)(pkt_data + 12)) != PTP_ETHER_TYPE) { DBG("PCAP payload ethertype received not IP or PTP: 0x%04xn", ntohs(*(u_short *)(pkt_data + 12))); /* do not count packets if from self */ } else if(memcmp(&netPath->interfaceInfo.hwAddress, pkt_data + 6, 6)) { netPath->receivedPackets++; } } else { /* Retrieve source IP from the payload - 14 eth + 12 IP */ netPath->lastSourceAddr = *(Integer32 *)(pkt_data + 26); /* Retrieve destination IP from the payload - 14 eth + 16 IP */ netPath->lastDestAddr = *(Integer32 *)(pkt_data + 30); /* do not count packets from self */ if(netPath->lastSourceAddr != netPath->interfaceAddr.s_addr) { netPath->receivedPackets++; } } netPath->receivedPacketsTotal++; /* XXX Total cheat */ memcpy(buf, pkt_data + netPath->headerOffset, pkt_header->caplen - netPath->headerOffset); fflush(NULL); ret = pkt_header->caplen - netPath->headerOffset; } #endif return ret; }
- 上面是接收
最后
以上就是高大战斗机为你收集整理的 PTPD2源码解析之:packet的接收和发送的全部内容,希望文章能够帮你解决 PTPD2源码解析之:packet的接收和发送所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复