完善上面代码 要求如:下若客户端进程正常结束,则服务器进程将退出「数据收发小循环」,并进入「请求受理大循环」,此时因为没有新的客户端请求,故而服务器进程将在accept()挂起; 。若服务器进程随后收到SIGINT信号,accept()将被立即中断,进程转而执行SIGINT信号处理器函数 handle_sigint() ,从而将sigint_flag 设置为1。 。当服务器完成SININT信号处理,重新回到accept()时,accept()不会自动恢复执行,而是立刻返回-1。此时服务器进程检查errno发现其值为ETNTR,说明accept()是因为服务器进程收到系统信号方被中断,故应该通过大循环重新启动accept(),除非导致accept()中断的信号为 STGINT|。 。若服务器在大循环判定时,发现引发accept()中断的确实是SIGINT,即可退出大循环,清理资源,从 main()使用return()退出程序。
时间: 2024-04-09 12:28:49 浏览: 117
TCP.rar_C# TCP收发数据_TCP收发_c tcp 服务器_c# tcp 收发_c语言 tcp
以下是经过修改的TCP单进程循环服务器程序(server.py):
```python
import socket
import signal
import sys
# SIGINT信号处理函数
def handle_sigint(sig, frame):
global sigint_flag
sigint_flag = 1
def run_server():
signal.signal(signal.SIGINT, handle_sigint)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 8888))
server_socket.listen(1)
print('Server started. Listening for connections...')
while True:
try:
client_socket, client_address = server_socket.accept()
print('Client connected:', client_address)
while True:
data = client_socket.recv(1024)
if not data:
break
print('Received from client:', data.decode())
client_socket.sendall(data)
if data.decode() == 'EXIT':
break
print('Client disconnected:', client_address)
client_socket.close()
if sigint_flag == 1:
break
except socket.error as e:
if e.errno == errno.EINTR and sigint_flag == 1:
break
else:
raise
print('Server shutting down...')
server_socket.close()
sys.exit(0)
if __name__ == '__main__':
sigint_flag = 0
run_server()
```
在这个修改后的代码中,我们添加了SIGINT信号处理函数`handle_sigint()`来处理服务器进程收到SIGINT信号时的情况。当服务器进程收到SIGINT信号时,`handle_sigint()`函数将设置`sigint_flag`为1。
在服务器的主循环中,我们添加了额外的逻辑来处理SIGINT信号的中断。如果`sigint_flag`为1,表示服务器收到了SIGINT信号,我们将退出大循环并清理资源。
在异常处理部分,我们检查`socket.error`异常的错误代码是否为`errno.EINTR`,同时检查`sigint_flag`是否为1。如果满足这两个条件,说明accept()被SIGINT信号中断,我们可以退出大循环。
最后,当服务器进程完成SIGINT信号处理后,我们调用`sys.exit(0)`来退出程序。
请注意,客户端程序无需修改,因为客户端进程的正常结束已经在原始代码中处理好了。
阅读全文