写了一个Socket Server 程序,该程序在监听client端的socket request的请求的同时可以接受command行的输入,可以接受一些Command 输入并相应, 如果命令行输入QUIT, 这个Socket server程序会退出。
学校要求写一个自动测试程序,这样问题变得有些复杂, 需要在后台启动这个server程序,并接受pipe来的in文件, 在处理玩pipe来的in文件处理后, 等待一段时间接受client端的链接请求, 最后接受QUIT指令结束程序。
总结下来就是时序如下:
假设程序为 a.out , 输入文件为 a.in
Step1 : a.out < a.in
Step2: wait some times for client socket input
Step3: input "QUIT" to a.out 让 a.out退出
最开始的做法是使用Bash
a.out < a.in &
PID=$!
sleep(5)
kill -9 $PID
因为step1之后a.out的输入被pipe接管了,没有办法再输入'QUIT‘, 就使用kill -9强杀了。由于使用的是socket, 有时候会导致socket没有正常结束,下一次启动的时候会出现bind错误。
研究了一段时间后,发现用python的subprocess可以解决这个问题,让程序优雅的退出。
import subprocess
import time
import sys
def main(btide_param, input_filename, output_filename):
command = ["btide", btide_param]
# Reading input data from file
with open(input_filename, "r") as file:
btide_in = file.read()
# Determine how to handle output based on whether an output file was provided
if output_filename is None:
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
stdout_destination = None
else:
output_fd = open(output_filename, "w")
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=output_fd, stderr=subprocess.PIPE, text=True)
stdout_destination = output_fd
# Sending initial input
process.stdin.write(btide_in)
process.stdin.flush()
# Introducing a delay
time.sleep(1)
# Sending subsequent commands
process.stdin.write('\nQUIT\n')
process.stdin.flush()
# Closing stdin to indicate no more input will be sent
# process.stdin.close()
# Handling output and waiting for process to finish
if stdout_destination is None:
# Reading output directly if no file is used
output, errors = process.communicate()
if errors:
print("Errors:", errors)
print(output)
else:
# Waiting for the process to complete if output is redirected to a file
process.stdin.close()
process.wait()
stdout_destination.close()
if __name__ == "__main__":
btide_args = sys.argv[1] if len(sys.argv) > 1 else ""
file_in = sys.argv[2] if len(sys.argv) > 2 else ""
file_out = sys.argv[3] if len(sys.argv) > 3 else None
print(f"args={btide_args}, in={file_in}, out={file_out}")
main(btide_args, file_in, file_out)
这里碰到的坑是如果结果需要输出到文件中, 再process.wait()前需要调用process.stdin.close(). 如果是直接输出到屏幕上, 要调用process.communicate()去等待程序结束。至于为什么还没有搞明白。总之,可以工作了。