我有一个正在侦听TCP和UDP数据包的接收器。我还有一个foo()def,它可以同时运行并显示当前时间,并每5秒发送UDP数据包。
问题在于,当我按下Ctrl + C按钮以终止程序时,第一次没有终止它,我应该至少按下两次这些按钮。
我按照本post中的建议增加了加薪。在上一个问题中它对我有用,但是在我添加了其他部分之后,它不再起作用。
代码如下:
from __future__ import print_function
from select import select
import socket
from struct import pack
from struct import unpack
from collections import deque
host = '10.0.0.2'
port = 5005
backlog = 5
BUFSIZE = 4096
q = deque()
import time, threading
def foo():
try:
print(time.ctime())
threading.Timer(5, foo).start()
except KeyboardInterrupt:
print('\nClosing')
raise
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def send(sock2, data2):
while data2:
sent = sock2.send(data2)
data2 = data2[sent:]
def send_file(ipToTransfer, fname):
with open(fname, 'rb') as f:
sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock2.connect((ipToTransfer, 5005))
except socket.error as err:
print(err, ipToTransfer, 5005)
sock2.close()
return
# Send the file name length & the filename itself in one packet
send(sock2, pack('B', len(fname)) + fname.encode())
while True:
data2 = f.read(BUFSIZE)
if not data2:
break
send(sock2, data2)
sock2.close()
def read_tcp(s):
conn, addr = s.accept()
print('Connected with', *addr)
# Create a buffer for this connection
receiver = Receiver(conn)
# Get the length of the file name
name_size = unpack('B', receiver.get(1))[0]
name = receiver.get(name_size).decode()
q.append(name)
print('name', name)
# Save the file
receiver.save(name)
conn.close()
print('saved\n')
def read_udp(s):
data,addr = s.recvfrom(1024)
print("received message:", data)
def run():
# create tcp socket
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
tcp.bind((host,port))
except socket.error as err:
print('Bind failed', err)
return
tcp.listen(1)
# create udp socket
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
udp.bind((host,port))
print('***Socket now listening at***:', host, port)
input = [tcp,udp]
try:
while True:
inputready,outputready,exceptready = select(input,[],[])
for s in inputready:
if s == tcp:
read_tcp(s)
elif s == udp:
read_udp(s)
else:
print("unknown socket:", s)
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
raise
tcp.close()
udp.close()
if __name__ == '__main__':
foo()
run()
我第一次按Ctrl + C
时,程序不会终止,我需要第二次按它们。怎么了?第一次按下Ctrl + C
怎么杀死程序?
答案 0 :(得分:1)
首次按下ctrl + c
时,它将终止您当前所在的线程,但不会终止正在运行程序其余部分的主线程。当您第二次这样做时,您将终止主线程
答案 1 :(得分:1)
如何通过第一次按
public class ReadTxtFileResult { public Stack Stack { get; set; } public DataTable DataTable { get; set; } }
来终止程序?
一种简单的方法是删除信号处理程序,并让进程立即在SIGINT上终止。将其放在代码开头附近:
public ReadTxtFileResult ReadTxtFile(string Flepath)
{
Stack stk = new Stack();
DataTable dt = new DataTable();
return new ReadTxtFileResult
{
Stack = stk,
DataTable = dt
}
}
另一个选择是您可以按Ctrl + C
发送SIGQUIT而不是SIGINT。在大多数程序中无需更改代码即可使用此功能...但是可能会生成核心转储。
请注意,通过执行上述任一操作,您将抢夺该程序执行正常关机的能力。但这对于大多数程序而言可能并不重要,因为操作系统将在终止时清除未使用的资源。