测试同事提单反馈: 工具A的x功能会低概率失效, 但没有发现什么规律。事实上, 我也确实遇到过这个低概率问题, 但是没有深入去分析过它(实际上也不是什么概率不概率, 只要发生了, 就会一直发生, 直到某种条件出现改变)。 前段时间用360抢票, 要回家啊, 抢着抢着, 突然发现, A工具的x功能没法用了, 这次总算是重现到了这个低概率问题。 当时, 我的第一直觉是, 这可能是受了360的影响, 哈哈, 360经常被黑嘛。
我自己带了一个新同事, 我让他帮忙验证一下这个问题。 他关掉pc, 然后开机, 然后再用A工具的x功能, 发现正常。 猜测是360直接或者间接影响了, 但是, 猜测归猜测, 没有确凿的正确, 猜测也是白猜测, 不能让人信服。
于是进行深入分析, 发现是A工具的x功能中的bind函数返回失败, 查阅了一下资料, 怀疑到端口冲突了。 我知道, A工具的x功能会监听y端口(充当udp服务端), 难道pc上还有其他进程也在监听y端口? 在x功能异常的pc上, 用netstat -nao | find y 命令看了一下, 查到果然有某进程在监听y端口(udp), 并且显示了进程号z, 然后利用tasklist | findstr z 命令查看一下, 找出了进程的名字P. 原来, 是这个进程占用了z端口啊。
为了验证上述分析, 我们关掉了进程P, 然后A工具的x功能正常。 如果进程P已经启动, 那么此时A进程的x功能就用不了。 可见, 确实是端口冲突问题。
我后面又做了这样一个实验: 先打开A工具的x功能, 然后开启进程P对应的软件, 发现该软件有错误弹框提示(该软件的作者考虑很充分啊)。
下面, 我们来模拟一下吧:
场景一:
直接运行下面程序:
#include <stdio.h> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") int main() { WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(1, 1); WSAStartup(wVersionRequested, &wsaData); unsigned int sockSrv = socket(AF_INET, SOCK_DGRAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("0.0.0.0"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(514); int result = bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); printf("result is %d\n", result); printf("GetLastError() : %d\n", GetLastError()); SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); char recvBuf[100] = "xxx"; recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&addrClient, &len); printf("%s\n", recvBuf); closesocket(sockSrv); WSACleanup(); system("pause"); return 0; }结果是(正常):
result is 0
GetLastError() : 0
场景二:
先运行tftp32.exe, 该软件会占用514端口, 然后再运行上面的程序, 产生的结果为:
result is -1
GetLastError() : 10048
xxx
快看看, 产生异常了啊, 查阅一下就知道: 10048是端口冲突错误。 好准。
场景三:
先运行上面的程序(正常), 然后再与运行tftp32.exe, 发现tftp32.exe弹框提示错误了, 如下:
看到了吧, 也是10048错误。
那怎么解决A工具中x功能的这个问题呢? 学一下tftp32.exe, 直接弹出一个友好的提示框吧。 当然, 我们后续也会慢慢讲到地址重用, 来解决这类问题。
回到那个概率性的bug, 其实并不是什么概率不概率的, 只是某台pc上, 刚好在运行tftp32.exe而已。
备注一下:在Windows上,tasklist用来查询进程, 类似于Linux上的ps命令。 而Windows上的findstr类似于linux上的grep. 至于netstat, 太常见, 我就不说了。