Skip to content

修复ping时统计异常的问题#385

Open
Kelephant wants to merge 1 commit intoithewei:masterfrom
Kelephant:master
Open

修复ping时统计异常的问题#385
Kelephant wants to merge 1 commit intoithewei:masterfrom
Kelephant:master

Conversation

@Kelephant
Copy link

【问题】
该IP是可以被ping通的,但是在ping过程中收到无效包,程序并没有再继续等待ping echo,而是继续发送ping req,导致后面回来的ping echo没有被标记为ok
root@localhost:/share/wenqikai# ./ping 5.5.12.101
64 bytes from 5.5.12.101: icmp_seq=1 ttl=64 time=0.5 ms
recv invalid icmp packet!
recv invalid icmp packet!
recv invalid icmp packet!
--- 5.5.12.101 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 1002 ms(--> 收到4个包, 没有丢失,实际上把无效包也统计在内了)
rtt min/avg/max = 0.460/0.460/0.460 ms
ping 4 count, 1 ok.(--> 这里显示只有1个有效包)

【解决方案】
收到无效包时,继续接收ping echo。如1s内未接收不到有效ping echo包,再发送下一个ping req

Update icmp.c
@Kelephant Kelephant changed the title 更新 icmp.c 修复ping时统计异常的问题 May 19, 2023
@ithewei ithewei requested a review from Copilot March 11, 2026 04:17
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 针对 protocol/icmp.cping() 在收到无效 ICMP 包时的统计与等待逻辑进行修复,目标是在出现无效包时继续等待有效的 echo reply,并避免把无效包计入“received”统计。

Changes:

  • 新增按“单次 ping 请求”维度的接收重试逻辑:无效包时继续接收,超时后进入下一次发送
  • recv_cnt 的统计调整为仅在收到有效 echo reply 时递增,修正统计异常
  • 引入 cur_ping_start_tick 用于控制单次 ping 的等待窗口

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +83 to 90
_read_again:
if(gettick_ms() - cur_ping_start_tick >= PING_TIMEOUT) {
// recv timeout, send ping again.
continue;
}

int nrecv = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, &peeraddr.sa, &addrlen);
if (nrecv < 0) {
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

当前 _read_again 重试逻辑里每次都会再次调用带 SO_RCVTIMEO=PING_TIMEOUT 的 recvfrom()。如果在接近 1s 末尾收到一个无效包(例如 900ms),会马上进入下一次 recvfrom(),它又可能再阻塞 1s,导致单次 ping 实际等待时间超过 PING_TIMEOUT(最多接近 2*PING_TIMEOUT),与“1s 内收不到有效 echo 就发下一个”的目标不符。建议按截止时间计算剩余超时(remaining = PING_TIMEOUT - elapsed)并把 SO_RCVTIMEO 设置为 remaining 后再 recvfrom,或改用 poll/select 按 deadline 等待。

Copilot uses AI. Check for mistakes.
Comment on lines 89 to +92
int nrecv = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, &peeraddr.sa, &addrlen);
if (nrecv < 0) {
perror("recvfrom");
continue;
goto _read_again;
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recvfrom() 失败后无条件 perror 并 goto _read_again,会在非超时/中断类错误(例如 EBADF、EINVAL 等)时循环打印并拖到 PING_TIMEOUT 才进入下一轮,掩盖真实错误。建议仅在 errno 为 EINTR / EAGAIN(EWOULDBLOCK) / ETIMEDOUT 时重试;其他错误应直接退出循环并走 error 路径或返回错误码。

Copilot uses AI. Check for mistakes.
}
++recv_cnt;

end_hrtime = gethrtime_us();
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end_hrtime 在校验前(line 95)和校验通过后(line 112)被赋值两次,但只有后一次用于计算 rtt。建议删除前一次赋值,避免冗余并减少误解。

Suggested change
end_hrtime = gethrtime_us();

Copilot uses AI. Check for mistakes.
++send_cnt;
addrlen = sizeof(peeraddr);
_read_again:
if(gettick_ms() - cur_ping_start_tick >= PING_TIMEOUT) {
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的代码风格与本文件其他 if 语句不一致:使用了 if( 而不是 if (。建议保持一致的空格风格。

Suggested change
if(gettick_ms() - cur_ping_start_tick >= PING_TIMEOUT) {
if (gettick_ms() - cur_ping_start_tick >= PING_TIMEOUT) {

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants