Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java CTRL-C在Python中的行为不同_Java_Python_Sockets - Fatal编程技术网

Java CTRL-C在Python中的行为不同

Java CTRL-C在Python中的行为不同,java,python,sockets,Java,Python,Sockets,我最近开始学习Python(这里是长期Java程序员),目前正在编写一些简单的服务器程序。问题是,对于一段看似相似的代码,Java对应程序正确地响应SIGINT信号(Ctrl+C),而Python对应程序则没有。当使用单独的线程生成服务器时,就会看到这种情况。代码如下: //Java代码 包装; 导入java.io.*; 导入java.net。*; 公共类服务器测试{ 公共静态void main(最终字符串[]args)引发异常{ 最终线程t=新服务器(); t、 start(); } } 类服

我最近开始学习Python(这里是长期Java程序员),目前正在编写一些简单的服务器程序。问题是,对于一段看似相似的代码,Java对应程序正确地响应
SIGINT
信号(Ctrl+C),而Python对应程序则没有。当使用单独的线程生成服务器时,就会看到这种情况。代码如下:

//Java代码
包装;
导入java.io.*;
导入java.net。*;
公共类服务器测试{
公共静态void main(最终字符串[]args)引发异常{
最终线程t=新服务器();
t、 start();
}
}
类服务器扩展线程{
@凌驾
公开募捐{
试一试{
最终服务器插座=新服务器插座(12345);
while(true){
最终套接字clientSock=sock.accept();
clientSock.close();
}
}捕获(例外e){
e、 printStackTrace();
}
}
}
和Python代码:

#Python代码
导入线程、系统、套接字、信号
def startserver():
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s、 绑定(“”,12345))
s、 听(1)
尽管如此:
csock,caddr=s.accept()
csock.sendall('离开我的草坪孩子…\n')
csock.close()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
尝试:
t=threading.Thread(目标=startserver)
t、 开始()
除:
系统出口(1)
在上述两个代码片段中,我创建了一个简单的服务器,用于侦听给定端口上的TCP请求。在Java代码中按下Ctrl+C时,JVM退出,而在Python代码中,我得到的只是shell中的
^C
。停止服务器的唯一方法是按Ctrl+Z,然后手动终止进程

所以我想出了一个计划;为什么不让一个sighandler监听Ctrl+Z并退出应用程序?酷,所以我想出了:

导入线程、系统、套接字、信号
def startserver():
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s、 绑定(“”,12345))
s、 听(1)
尽管如此:
csock,caddr=s.accept()
csock.sendall('离开我的草坪孩子…\n')
csock.close()
def ctrlz_处理器(*args,**kwargs):
系统出口(1)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
尝试:
signal.signal(signal.SIGTSTP,ctrlz_处理器)
t=threading.Thread(目标=startserver)
t、 开始()
除:
系统出口(1)
但现在,我似乎把情况弄得更糟了!现在,在外壳上按Ctrl+C键发射“^C”,在外壳上按Ctrl+Z键发射“^Z”

所以我的问题是,为什么会有这种奇怪的行为?我可能会有多个服务器进程在同一进程中作为单独的线程运行,因此当进程接收到
SIGINT
时,是否有任何干净的方法杀死服务器?顺便说一句,在Ubuntu上使用Python2.6.4

TIA,
佐助

几个问题:

  • 不要捕获所有异常并静默退出。这是你能做的最糟糕的事情

  • 除非你真的知道自己在做什么,否则千万不要抓住SIGTSTP。这并不是一个让应用程序拦截的信号,如果你捕捉到了它,很可能是你做错了什么

  • 键盘中断只发送到程序的初始线程,而不会发送到其他线程。这样做有两个原因。通常,您希望在单个位置处理^C,而不是在碰巧接收异常的随机、任意线程中。此外,它有助于保证在正常操作中,大多数线程不会收到异步异常;这很有用,因为(在所有语言中,包括Java)很难可靠地处理它们

  • 在这里您永远不会看到键盘中断,因为主线程在启动次线程后立即退出。没有主线程来接收异常,它只是被丢弃

解决方法有两个:保持主线程,这样键盘中断就有了出路,并且只捕获键盘中断,而不是所有异常


  • 您创建的线程不是守护线程,因此当父线程退出时它不会退出

  • main在启动子线程后立即退出,python进程等待子线程终止

  • 关闭:不要忘记关闭插座

  • 您应该为子线程实现一些停止机制。一个简单的解决方法是:在接受客户端连接的while循环中检查一些
    stopped
    标志(使用模块级别,或者扩展
    threading.Thread
    类来封装它),将该标志设置为True,并(通过连接)在Ctrl+C和/或Ctrl+Z上启动服务器套接字,或者不使用它们;在主块中等待
    ,而t.isAlive():time.sleep(1)
    。下面是一个示例代码:

  • 导入线程、系统、套接字、信号、时间

    类服务器(threading.Thread): def初始化(自身): threading.Thread.init(self) self.\u stop=False 自身端口=12345

    def停止(自): 自停止=真 self.kick()

    def井涌(自): 尝试: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s、 连接(('',自身端口)) s、 关闭() 除IOError外,e: 打印“无法启动服务器:”,e

    def运行(自): s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s、 绑定(('',自身端口)) s、 听(1) 尝试: 尽管如此: csock,caddr=s.accept() 如果自行停止: 打印“停止,断开” 打破 打印“从连接的客户端”,caddr 尝试: csock.sendall('离开我的草坪孩子…\n') 最后: csock.close() 最后: s、 关闭()

    如果name='main': t=服务器() #如果它没有停止
    import threading, sys, socket, signal, time
    
    def startserver():
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('', 12345))
        s.listen(1)
        while True:
            csock, caddr = s.accept()
            csock.sendall('Get off my lawn kids...\n')
            csock.close()
    
    if __name__ == '__main__':
        try:
            t = threading.Thread(target=startserver)
            t.start()
    
            # Wait forever, so we can receive KeyboardInterrupt.
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            print "^C received"
            sys.exit(1)
    
        # We never get here.
        raise RuntimeError, "not reached"
    

    import threading, sys, socket, signal, time

    class Server(threading.Thread): def init(self): threading.Thread.init(self) self._stop = False self._port =12345

    def stop(self): self.__stop = True self.kick()

    def kick(self): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('', self.__port)) s.close() except IOError, e: print "Failed to kick the server:", e

    def run(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('', self._port)) s.listen(1) try: while True: csock, caddr = s.accept() if self._stop: print "Stopped, breaking" break print "client connected from", caddr try: csock.sendall('Get off my lawn kids...\n') finally: csock.close() finally: s.close()

    if name == 'main': t = Server() # if it is failed to stop the thread properly, it will exit t.setDaemon(True) t.start() try: while t.isAlive(): time.sleep(1) except: # Ctrl+C brings us here print "Maybe, you have interrupted this thing?" t.stop() # t.join() may be called here, or another synchronization should appear to # make sure the server stopped correctly