为公司的部署工程师书写了一个autoIt应用程序,现在遇到下面的一种情况:
产品分服务器端和客户端,启动的时候,会启用1785端口,然后彼此通信;
现在我的autoIt应用程序需要做的事情是:
如果1785端口被占用,该怎么办? 如果部署工程师熟悉配置文件,把端口1785更换成别的端口怎么办?
解决方案如下:
1. 产品开发组应该配置自己的端口为不常用端口,定义一个小的范围,于是可以通过AutoIt,判断目前配置的端口是否在1700-1710之间,只要在这个之间,就来判断该端口是否打开,如果打开了,就可以考虑关闭使用该端口的应用程序;如果不在 1700-1710之间,就给出提示信息:端口信息配置有误,让实施人员联系开发人员重新配置。
2. 调用dos命令,netstat -ano|findstr ":1701" 可以判断1701端口是否被占用。
如果返回的是空字符串,表明端口没有被占用,不影响配置文件的继续执行;
如果返回的端口不为空,就需要做以下几件事:
1) 获取使用1701端口的所有应用程序PID
;Get the PIDs which take the $port Func get_PIDs($port) $tcp_str = _GetDOSOutput('netstat -aon|findstr ":' & $port &'"') ;ConsoleWrite($tcp_str & @CRLF) $tcp_array = StringSplit($tcp_str, @CR) $len = UBound($tcp_array) Local $pids[$len-1] For $i = 1 To $len-1 $splits = StringSplit($tcp_array[$i], " ") $pid =_ArrayPop($splits) _ArrayPush($pids, $pid) Next Return _ArrayUnique($pids) EndFunc
2. 关闭使用了1701端口的应用程序
;Close the process by the known port Func close_process_by_port($port) $pids = get_PIDs($port) For $i = 1 To UBound($pids) -1 If $pids[$i] <> 0 And $pids[$i] <> "" Then close_process(Number($pids[$i])) EndIf Next EndFunc
3. 关于close_process 函数(以前该函数使用了判断语句:ProcessExists,如果存在就删除,不存在就不删除,但是这样会导致某些问题:程序被意外关闭了,此时内存中该程序还是存在的,可是ProcessExists 却判断不存在,就什么工作都不做了)
; Close some process Func close_process($process_name) ;We will close $process_name no matter it exists or not. ProcessClose($process_name) ProcessWaitClose($process_name) EndFunc
4. 关于_GetDOSOutput 函数,该函数是从别人那儿获取的,难点在参数 $STDERR_CHILD 以及 $STDOUT_CHILD,为了获取的结果准确,$sCommand尽量细节一些,确保该函数能获取想要的结果。
; Return the dos command output to a string Func _GetDOSOutput($sCommand) Local $iPID, $sOutput = "" $iPID = Run('"' & @ComSpec & '" /c ' & $sCommand, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) While 1 $sOutput &= StdoutRead($iPID, False, False) If @error Then ExitLoop EndIf Sleep(10) WEnd Return $sOutput EndFunc
5. 以上的准备工作完成之后,就可以完成主函数里面的内容了。
$port = get_tcp_port($sync_file) _GUICtrlListBox_AddString($hListBox, "Check port: " & $port & " whether it is in use or not") If $port > 1699 And $port < 1710 Then close_process_by_port($port) Else _GUICtrlListBox_AddString($hListBox, "端口: " & $port & " 不正确,请正确配置 sync.xml 文件节点 TCP:LocalHostPort") EndIf
该思路可以解决目前的问题,也许有人会觉得:凭啥关掉别人的程序?就因为端口占用了?难道不能新生成一个端口?
在测试自己的应用程序的时候,我尝试设置一些奇怪的端口,比喻1, 135,然后运行close_process_by_port,我发现系统会崩溃;
于是我设置关闭应用程序,也只有在端口在1700-1710之间,最大程度避免风险;
目前该应用程序会运行在局域网里面两台可以连接的机器上,如果我随机生成没有被占用的端口,就没法保证服务器,客户端端口的一致性。目前我还没有好的思路搞同步。