那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

深入了解IP數據報發送的過程

汽車電子技術 ? 來源:物聯網IoT開發 ? 作者:杰杰mcu ? 2023-02-14 10:24 ? 次閱讀

IP協議的功能

回顧一下前面寫的關于IP協議的文章:

IP協議基礎掃盲班

IP地址相關知識深入了解~

IP數據報分析

IP數據報結構、IP分片的原理與處理

IP數據報的收發

回顧一下前面的文章所提及的知識點,總結一下IP協議的功能,得到以下結論:

  1. 編址(目標端的IP地址),數據傳輸的過程當中就必須表明要發送目標端的IP地址
  2. 尋址和路由(根據對方的IP地址,尋找最佳路徑傳輸信息);
  3. 數據報的分片和重組。
  4. 傳遞服務是不可靠的(IP協議只是盡自己最大努力去傳輸數據包),它也是無連接的協議

IP數據報發送

IP協議是網絡層的主要協議,在上層傳輸協議(如TCP/UDP)需要發送數據時,會將數據封裝起來,然后傳遞到IP層,IP協議首先會根據上層協議的目標IP地址選擇一個合適的網卡進行發送數據( 路由),然后IP協議將再次封裝數據形成IP數據報,主要的操作就是填寫IP數據報首部對應的各個字段:目標IP地址、源IP地址、協議類型、生存時間等,最后在IP層通過回調函數netif->output(即etharp_output()函數)將IP數據報投遞給ARP,再調用網卡底層發送函數進行發送,這樣子自上而下的數據就發送出去,IP協議以目標IP地址作為目標主機的身份地址。

  1. /**

  2. * ip_output_if的簡化版接口。它找到發送數據包的netif網絡接口并調用ip_output_if來完成實際工作。

  3. *

  4. * @param p 要發送的數據包(p->payload(有效負載)指向數據,如果dest == LWIP_IP_HDRINCL,則p已包含IP頭和p->有效負載指向該IP頭)

  5. * @param src 要發送的源IP地址(如果src == IP4_ADDR_ANY,則用發送的netif綁定的IP地址用作源地址)

  6. * @param dest 目的IP地址

  7. * @param ttl 要在IP標頭中設置的TTL值(生存時間)

  8. * @param tos 用于在IP標頭中設置的TOS值

  9. * @param proto 將在IP頭中設置對應的上層協議

  10. * @return ERR_OK 如果數據包發送正常就返回ok,

  11. * 如果p沒有足夠的空間用于IP /LINK標頭,則為ERR_BUF

  12. * 其他則返回netif->output返回的錯誤

  13. * @return ERR_RTE如果沒有找到路線

  14. * 請參閱ip_output_if()以獲取更多返回值

  15. */

  16. err_t

  17. ip4_output(struct pbuf *p,constip4_addr_t*src,constip4_addr_t*dest,

  18. u8_t ttl,u8_t tos,u8_t proto)

  19. {

  20. struct netif *netif;


  21. LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);


  22. //根據目標IP地址找到對應的網卡發送數據

  23. if((netif = ip4_route_src(src, dest))== NULL){

  24. LWIP_DEBUGF(IP_DEBUG,("ip4_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\\n",

  25. ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));

  26. IP_STATS_INC(ip.rterr);

  27. return ERR_RTE;

  28. }


  29. return ip4_output_if(p, src, dest, ttl, tos, proto, netif);

  30. }

路由過程的實現

路由(routing)就是通過互聯的網絡把信息從源地址傳輸到目的地址的活動,發送端必然需要找到一個網卡將數據報發送出去,而實現這個過程的函數就是 ip4_route_src()

其實lwip對 ip4_route_src()函數進行了重新定義,實際上是調用了 ip4_route()函數。這個函數的原理就是根據指定的IP地址找到合適的網卡 netif,然后返回,前面的文章也提到過,lwip的網卡是通過 netif_list列表管理的,那么找網卡的操作也必然是遍歷網卡列表 netif_list,判斷網卡是否已經掛載并且IP地址是否有效,如果連網卡都找不到,那就不用發送數據了,返回null。

  1. #define ip4_route_src(src, dest) ip4_route(dest)

  1. /**

  2. *為給定的IP地址查找適當的網絡接口。

  3. *它搜索網絡接口列表。找到匹配項

  4. *

  5. *@param dest 要查找路由的目標IP地址

  6. *@return 發送到達目的地的網卡 netif

  7. */

  8. struct netif *

  9. ip4_route(constip4_addr_t*dest)

  10. {

  11. #if!LWIP_SINGLE_NETIF

  12. struct netif *netif;


  13. LWIP_ASSERT_CORE_LOCKED();


  14. #if LWIP_MULTICAST_TX_OPTIONS

  15. /*默認使用管理選擇的接口進行多播*/

  16. if(ip4_addr_ismulticast(dest)&& ip4_default_multicast_netif){

  17. return ip4_default_multicast_netif;

  18. }

  19. #endif /* LWIP_MULTICAST_TX_OPTIONS */


  20. /* bug #54569: in case LWIP_SINGLE_NETIF=1 and LWIP_DEBUGF() disabled, the following loop is optimized away */

  21. LWIP_UNUSED_ARG(dest);


  22. /*遍歷網卡列表netif_list */

  23. NETIF_FOREACH(netif){

  24. /* 如果網卡已經掛載并且IP地址是有效的 */

  25. if(netif_is_up(netif)&& netif_is_link_up(netif)&&!ip4_addr_isany_val(*netif_ip4_addr(netif))){

  26. /* 網絡掩碼匹配? */

  27. if(ip4_addr_netcmp(dest, netif_ip4_addr(netif), netif_ip4_netmask(netif))){

  28. /* 返回找到的網卡netif */

  29. return netif;

  30. }

  31. /* 網關在非廣播接口上匹配?(即在點對點接口中對等) */

  32. if(((netif->flags & NETIF_FLAG_BROADCAST)==0)&& ip4_addr_cmp(dest, netif_ip4_gw(netif))){

  33. /* 返回找到的網卡netif */

  34. return netif;

  35. }

  36. }

  37. }


  38. #if LWIP_NETIF_LOOPBACK &&!LWIP_HAVE_LOOPIF /**如果打開環回地址的宏定義 */

  39. /* loopif is disabled, looopback traffic is passed through any netif */

  40. if(ip4_addr_isloopback(dest)){

  41. /*不檢查環回流量的鏈接*/

  42. if(netif_default != NULL && netif_is_up(netif_default)){

  43. return netif_default;

  44. }

  45. /*默認netif沒有啟動,只需使用任何netif進行環回流量*/

  46. NETIF_FOREACH(netif){

  47. if(netif_is_up(netif)){

  48. return netif;

  49. }

  50. }

  51. return NULL;

  52. }

  53. #endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */


  54. #ifdef LWIP_HOOK_IP4_ROUTE_SRC

  55. netif = LWIP_HOOK_IP4_ROUTE_SRC(NULL, dest);

  56. if(netif != NULL){

  57. return netif;

  58. }

  59. #elif defined(LWIP_HOOK_IP4_ROUTE)

  60. netif = LWIP_HOOK_IP4_ROUTE(dest);

  61. if(netif != NULL){

  62. return netif;

  63. }

  64. #endif

  65. #endif /* !LWIP_SINGLE_NETIF */


  66. if((netif_default == NULL)||!netif_is_up(netif_default)||!netif_is_link_up(netif_default)||

  67. ip4_addr_isany_val(*netif_ip4_addr(netif_default))|| ip4_addr_isloopback(dest)){

  68. /*找不到匹配的netif,默認的netif不可用。建議使用LWIP_HOOK_IP4_ROUTE()*/

  69. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\\n",

  70. ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));

  71. IP_STATS_INC(ip.rterr);

  72. MIB2_STATS_INC(mib2.ipoutnoroutes);

  73. return NULL;

  74. }


  75. return netif_default;

  76. }

ip4_output_if函數

找到網卡之后就調用 ip4_output_if()函數將數據發送出去,這個函數會指定發送數據的網卡,同時會將來自上層協議(tcp、udp)的數據進行封裝,組成IP數據報再發送,不過這個函數層層調用,比較麻煩,具體如下:。

  1. /**

  2. * 在網絡接口上發送IP數據包。這個函數構造IP數據包首部并計算IP頭校驗和,

  3. * 如果源IP地址為NULL,在發送的時候就填寫發送網卡的IP地址為源IP地址

  4. * 如果目標IP地址是LWIP_IP_HDRINCL,則假定pbuf已經存在包括IP頭和有效負載指向它而不是數據。

  5. *

  6. * @param p 要發送的數據包(p->payload(有效負載)指向數據,如果dest == LWIP_IP_HDRINCL,則p已包含IP頭和p->有效負載指向該IP頭)

  7. * @param src 要發送的源IP地址(如果src == IP4_ADDR_ANY,則用發送的netif綁定的IP地址用作源地址)

  8. * @param dest 目的IP地址

  9. * @param ttl 要在IP標頭中設置的TTL值(生存時間)

  10. * @param tos 用于在IP標頭中設置的TOS值

  11. * @param proto 將在IP頭中設置對應的上層協議

  12. * @param netif 發送此數據包的netif

  13. * @return ERR_OK 如果數據包發送正常就返回ok,

  14. * 如果p沒有足夠的空間用于IP /LINK標頭,則為ERR_BUF

  15. * 其他則返回netif->output返回的錯誤

  16. *

  17. * @note ip_id:RFC791“某些主機可能只需使用

  18. * 獨立于目的地的唯一標識符“

  19. */

  20. err_t

  21. ip4_output_if(struct pbuf *p,constip4_addr_t*src,constip4_addr_t*dest,

  22. u8_t ttl,u8_t tos,

  23. u8_t proto,struct netif *netif)

  24. {

  25. #if IP_OPTIONS_SEND

  26. return ip4_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL,0);

  27. }

  1. /**

  2. * 與ip_output_if()相同,但可以包含IP選項:

  3. *

  4. * @param ip_options指向IP選項的指針,復制到IP頭中

  5. * @param optlen ip_options的長度

  6. */

  7. err_t

  8. ip4_output_if_opt(struct pbuf *p,constip4_addr_t*src,constip4_addr_t*dest,

  9. u8_t ttl,u8_t tos,u8_t proto,struct netif *netif,void*ip_options,

  10. u16_t optlen)

  11. {

  12. #endif /* IP_OPTIONS_SEND */

  13. constip4_addr_t*src_used = src;

  14. if(dest != LWIP_IP_HDRINCL){

  15. if(ip4_addr_isany(src)){

  16. src_used = netif_ip4_addr(netif);

  17. }

  18. }


  19. #if IP_OPTIONS_SEND

  20. return ip4_output_if_opt_src(p, src_used, dest, ttl, tos, proto, netif,

  21. ip_options, optlen);

  22. #else/* IP_OPTIONS_SEND */

  23. return ip4_output_if_src(p, src_used, dest, ttl, tos, proto, netif);

  24. #endif /* IP_OPTIONS_SEND */

  25. }

ip4_output_if_opt_src

首先看看這個函數到底做了什么吧:在上層協議遞交數據包后,通過層層調用,最終到 ip4_output_if_opt_src()函數中處理,它的處理如下:圖片代碼的實現如下:注釋非常豐富。主要過程就是:

  1. 判斷是否填寫好IP數據報首部?若目標IP地址為LWIPIPHDRINCL表示已經填寫好IP數據報首部,且payload指針也指向了IP數據報首部。
  2. 如果沒有填寫IP數據報首部,調用 pbuf_add_header()函數調整數據區域指針以指向IP數據報首部。
  3. 填寫IP數據報中的生存時間、服務類型、上層協議、目標IP地址、版本號與首部長度、數據報總長度、標志位和分片偏移量、標識、源IP地址等內容,總之就是將IP數據報首部的內容該填的都填上。
  4. 如果目標IP地址是自己的網卡IP地址,調用環回輸入函數 netif_loop_output()發送IP數據報給自己,這種處理一般是用于測試代碼。
  5. 如果IP數據報太大,數據報總長度大于網卡的MTU,則需要進行分片處理,調用 ip4_frag()函數進行發送。
  6. 直接調用注冊的 netif->output接口傳遞給ARP,實際上就是調用 etharp_output()函數,在這里它會將IP地址解析成對應的 MAC地址,并且調用網卡發送函數進行發送。
  1. /**

  2. * 與ip4_output_if_opt()相同,當源地址是'IP4_ADDR_ANY'時,'src'地址不會被netif地址替換

  3. */

  4. err_t

  5. ip4_output_if_opt_src(struct pbuf *p,constip4_addr_t*src,constip4_addr_t*dest,

  6. u8_t ttl,u8_t tos,u8_t proto,struct netif *netif,void*ip_options,

  7. u16_t optlen)

  8. {

  9. #endif /* IP_OPTIONS_SEND */

  10. struct ip_hdr *iphdr;

  11. ip4_addr_t dest_addr;

  12. #if CHECKSUM_GEN_IP_INLINE

  13. u32_t chk_sum =0;

  14. #endif /* CHECKSUM_GEN_IP_INLINE */


  15. LWIP_ASSERT_CORE_LOCKED();

  16. LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p);


  17. MIB2_STATS_INC(mib2.ipoutrequests);


  18. /* 應該要構建IP首部還是已經包含在pbuf中了?如果是要構建IP數據報首部 */

  19. if(dest != LWIP_IP_HDRINCL){

  20. u16_t ip_hlen = IP_HLEN;

  21. #if IP_OPTIONS_SEND

  22. u16_t optlen_aligned =0;

  23. if(optlen !=0){

  24. #if CHECKSUM_GEN_IP_INLINE

  25. int i;

  26. #endif /* CHECKSUM_GEN_IP_INLINE */

  27. if(optlen >(IP_HLEN_MAX - IP_HLEN)){

  28. /* 選項字段太長 */

  29. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_output_if_opt: optlen too long\\n"));

  30. IP_STATS_INC(ip.err);

  31. MIB2_STATS_INC(mib2.ipoutdiscards);

  32. return ERR_VAL;

  33. }

  34. /* 選項字段按照4字節對齊 */

  35. optlen_aligned =(u16_t)((optlen +3)&~3);

  36. ip_hlen =(u16_t)(ip_hlen + optlen_aligned);

  37. /* 首先寫入IP選項字段 */

  38. if(pbuf_add_header(p, optlen_aligned)){

  39. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_output_if_opt: not enough room for IP options in pbuf\\n"));

  40. IP_STATS_INC(ip.err);

  41. MIB2_STATS_INC(mib2.ipoutdiscards);

  42. return ERR_BUF;

  43. }

  44. MEMCPY(p->payload, ip_options, optlen);

  45. if(optlen < optlen_aligned){

  46. /* 剩余字節清零 */

  47. memset(((char*)p->payload)+ optlen,0,(size_t)(optlen_aligned - optlen));

  48. }

  49. #if CHECKSUM_GEN_IP_INLINE

  50. for(i =0; i < optlen_aligned /2; i++){

  51. chk_sum +=((u16_t*)p->payload)[i];

  52. }

  53. #endif /* CHECKSUM_GEN_IP_INLINE */

  54. }

  55. #endif /* IP_OPTIONS_SEND */

  56. /* 生成IP頭 */

  57. if(pbuf_add_header(p, IP_HLEN)){

  58. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_output: not enough room for IP header in pbuf\\n"));


  59. IP_STATS_INC(ip.err);

  60. MIB2_STATS_INC(mib2.ipoutdiscards);

  61. return ERR_BUF;

  62. }


  63. iphdr =(struct ip_hdr *)p->payload;

  64. LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",

  65. (p->len >=sizeof(struct ip_hdr)));


  66. IPH_TTL_SET(iphdr, ttl);

  67. IPH_PROTO_SET(iphdr, proto);

  68. #if CHECKSUM_GEN_IP_INLINE

  69. chk_sum += PP_NTOHS(proto |(ttl <<8));

  70. #endif /* CHECKSUM_GEN_IP_INLINE */


  71. /* 構建目的IP地址,此處的目的IP地址不能為NULL */

  72. ip4_addr_copy(iphdr->dest,*dest);

  73. #if CHECKSUM_GEN_IP_INLINE

  74. chk_sum += ip4_addr_get_u32(&iphdr->dest)&0xFFFF;

  75. chk_sum += ip4_addr_get_u32(&iphdr->dest)>>16;

  76. #endif /* CHECKSUM_GEN_IP_INLINE */


  77. IPH_VHL_SET(iphdr,4, ip_hlen /4);

  78. IPH_TOS_SET(iphdr, tos);

  79. #if CHECKSUM_GEN_IP_INLINE

  80. chk_sum += PP_NTOHS(tos |(iphdr->_v_hl <<8));

  81. #endif /* CHECKSUM_GEN_IP_INLINE */

  82. IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));

  83. #if CHECKSUM_GEN_IP_INLINE

  84. chk_sum += iphdr->_len;

  85. #endif /* CHECKSUM_GEN_IP_INLINE */

  86. IPH_OFFSET_SET(iphdr,0);

  87. IPH_ID_SET(iphdr, lwip_htons(ip_id));

  88. #if CHECKSUM_GEN_IP_INLINE

  89. chk_sum += iphdr->_id;

  90. #endif /* CHECKSUM_GEN_IP_INLINE */

  91. ++ip_id;


  92. if(src == NULL){

  93. ip4_addr_copy(iphdr->src,*IP4_ADDR_ANY4);/** 構建源IP地址 */

  94. }else{

  95. /* 此處的源IP地址不能為NULL */

  96. ip4_addr_copy(iphdr->src,*src);

  97. }


  98. #if CHECKSUM_GEN_IP_INLINE

  99. chk_sum += ip4_addr_get_u32(&iphdr->src)&0xFFFF;

  100. chk_sum += ip4_addr_get_u32(&iphdr->src)>>16;

  101. chk_sum =(chk_sum >>16)+(chk_sum &0xFFFF);

  102. chk_sum =(chk_sum >>16)+ chk_sum;

  103. chk_sum =~chk_sum;

  104. IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP){

  105. iphdr->_chksum =(u16_t)chk_sum;/* network order */

  106. }

  107. #if LWIP_CHECKSUM_CTRL_PER_NETIF

  108. else{

  109. IPH_CHKSUM_SET(iphdr,0);

  110. }

  111. #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/

  112. #else/* CHECKSUM_GEN_IP_INLINE */

  113. IPH_CHKSUM_SET(iphdr,0);

  114. #if CHECKSUM_GEN_IP

  115. IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP){

  116. IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));

  117. }

  118. #endif /* CHECKSUM_GEN_IP */

  119. #endif /* CHECKSUM_GEN_IP_INLINE */

  120. }else{

  121. /* IP頭已包含在pbuf中 */

  122. if(p->len < IP_HLEN){

  123. /** pbuf的長度小于IP數據報首部長度(20字節) */

  124. LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,("ip4_output: LWIP_IP_HDRINCL but pbuf is too short\\n"));

  125. IP_STATS_INC(ip.err);

  126. MIB2_STATS_INC(mib2.ipoutdiscards);

  127. return ERR_BUF;

  128. }

  129. iphdr =(struct ip_hdr *)p->payload;/** 直接從數據區域獲取IP數據報首部 */

  130. ip4_addr_copy(dest_addr, iphdr->dest);/** 獲取目的IP地址 */

  131. dest =&dest_addr;

  132. }


  133. IP_STATS_INC(ip.xmit);


  134. LWIP_DEBUGF(IP_DEBUG,("ip4_output_if: %c%c%"U16_F"\\n", netif->name[0], netif->name[1],(u16_t)netif->num));

  135. ip4_debug_print(p);


  136. #if ENABLE_LOOPBACK /** 換回接口 */

  137. if(ip4_addr_cmp(dest, netif_ip4_addr(netif))

  138. #if!LWIP_HAVE_LOOPIF

  139. || ip4_addr_isloopback(dest)

  140. #endif /* !LWIP_HAVE_LOOPIF */

  141. ){

  142. /* 數據包是給自己的,將其放入環回接口 */

  143. LWIP_DEBUGF(IP_DEBUG,("netif_loop_output()"));

  144. return netif_loop_output(netif, p);

  145. }

  146. #if LWIP_MULTICAST_TX_OPTIONS

  147. if((p->flags & PBUF_FLAG_MCASTLOOP)!=0){

  148. netif_loop_output(netif, p);

  149. }

  150. #endif /* LWIP_MULTICAST_TX_OPTIONS */

  151. #endif /* ENABLE_LOOPBACK */

  152. #if IP_FRAG

  153. /** 要發送的數據報大于mtu,需要分片,此處的前提是使能了IP_FRAG (IP分片) */

  154. if(netif->mtu &&(p->tot_len > netif->mtu)){

  155. return ip4_frag(p, netif, dest);/** 調用IP數據報分片函數將數據報分片發送出去 */

  156. }

  157. #endif /* IP_FRAG */


  158. LWIP_DEBUGF(IP_DEBUG,("ip4_output_if: call netif->output()\\n"));

  159. return netif->output(netif, p, dest);/** 如果不需要分片就直接通過網卡發送出去,netif->output() */

  160. }

最后提個醒

此外:上層協議是不會直接調用 ip4_output()函數的,lwip是通過宏定義將 ip4_output()函數進行重新定義:

  1. #define ip_output(p, src, dest, ttl, tos, proto) ip4_output(p, src, dest, ttl, tos, proto

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • IP協議
    +關注

    關注

    3

    文章

    85

    瀏覽量

    21692
  • 傳輸協議
    +關注

    關注

    0

    文章

    78

    瀏覽量

    11493
  • 網絡層
    +關注

    關注

    0

    文章

    40

    瀏覽量

    10337
收藏 人收藏

    評論

    相關推薦

    深入了解示波器

    深入了解示波器
    發表于 11-14 22:32

    專家開講:深入了解電池技術──Part 3

    資深工程師 Ivan Cowie 的「深入了解電池技術」專欄Part 3來啰!這次要介紹的是鉛酸電池(lead-acidbatteries)技術。鉛酸電池是在1859年由法國物理學家Gaston
    發表于 08-18 09:37

    單片機的深入了解

    項目名稱:單片機的深入了解!項目是否開源:否申請開發板數量:1 塊申請人團隊介紹:我們團隊由五個人組成,我們打算開始著手單片機的程序改編,設計一些比較特殊新穎的東西!希望給以支持!
    發表于 10-12 20:00

    深入了解LabVIEW FPGA資料分享

    深入了解LabVIEW FPGA
    發表于 05-27 08:35

    深入了解獨立式數據采集系統CompactDAQ

    深入了解獨立式數據采集系統CompactDAQ
    發表于 05-11 07:10

    請問網絡中IP數據報傳輸的過程是怎樣的?

    請問網絡中IP數據報傳輸的過程是怎樣的?
    發表于 10-27 07:03

    如何使用Winpcap接收和發送IP數據報文?

    如何使用Winpcap接收和發送IP數據報文?如何解決在Windows上配置雙協議棧的一些問題?
    發表于 12-24 06:15

    介紹IP數據報的格式及IP相關功能在Lwip中的實現方式

    1、IP報文基礎及其在Lwip的實現IP協議是TCP/IP協議中最為核心的協議,所有的TCP、UDP、ICMP及IGMP數據都已IP
    發表于 08-23 17:38

    示波器的深入了解

    示波器的深入了解 引言自然界運行著各種形式的正弦波,比如海浪、地震、聲波、爆破、空氣中傳播的聲音,或者身體運轉的自然節律。物理世界里,能
    發表于 11-04 11:53 ?52次下載
    示波器的<b class='flag-5'>深入了解</b>

    深入了解示波器入門手冊

    深入了解示波器入門手冊
    發表于 03-27 17:43 ?241次下載
    <b class='flag-5'>深入了解</b>示波器入門手冊

    深入了解電路噪聲的那些事

    模擬電子的相關知識學習教材資料——深入了解電路噪聲的那些事
    發表于 09-27 15:19 ?0次下載

    深入了解電感與磁珠的異同

    模擬電子的相關知識學習教材資料——深入了解電感與磁珠的異同
    發表于 09-27 15:19 ?0次下載

    帶你深入了解示波器

    帶你深入了解示波器
    發表于 02-07 14:26 ?19次下載

    深入了解安全光柵

    深入了解安全光柵
    的頭像 發表于 06-25 13:53 ?1271次閱讀
    <b class='flag-5'>深入了解</b>安全光柵

    深入了解 GaN 技術

    深入了解 GaN 技術
    的頭像 發表于 12-06 17:28 ?6240次閱讀
    <b class='flag-5'>深入了解</b> GaN 技術
    豪华百家乐桌子| 乐博国际| 赌场百家乐官网打法| 东营区百家乐艺术团| 百家乐官网作弊演示| 百家乐美食坊| 台东市| 百家乐的方法和公式| 大发88817| 真人百家乐官网赌场娱乐网规则| 威尼斯人娱乐棋牌| 百家乐官网注册18元体验金| 金满堂百家乐的玩法技巧和规则| 百家乐官网关键词| 百家乐百博亚洲| 哪里有百家乐官网赌博网站| 百家乐百家乐视频| 贺州市| 赌博百家乐判断决策| 百家乐官网赔率技巧| 百家乐必胜赌| 澳门百家乐官网游戏说明| 百家百家乐官网网站| 网上百家乐官网做假| 大发888玩哪个| 百家乐官网娱乐平台备用网址 | 百家乐视频世界| 威尼斯人娱乐代理注| 百家乐官网网上真钱娱乐平台| 太阳城会员| 芝加哥百家乐官网的玩法技巧和规则 | 百家乐三遍| 澳门百家乐官网几副牌| 老虎机破解方法| 布加迪百家乐官网的玩法技巧和规则 | 大发888备用网站| 百家乐官网平注资讯| 申扎县| 机器百家乐软件| 送58百家乐官网的玩法技巧和规则 | 發中發百家乐官网的玩法技巧和规则 |