Python 为什么主机正在中止连接?

Python 为什么主机正在中止连接?,python,networking,Python,Networking,我在自学Python网络,我回忆起,当我自学线程时,我遇到了,所以我复制了脚本,为Python 3.1.1更新了脚本,并运行了它们。他们工作得很好 然后我做了一些修改。我的目标是做一些简单的事情: 客户端pickle一个整数并将其发送到服务器 服务器接收pickle整数,取消pickle,将其加倍,然后pickle并将其发送回客户端 客户机接收pickle(和double)整数,取消pickle并输出它 这是服务器: import pickle import socket import thre

我在自学Python网络,我回忆起,当我自学线程时,我遇到了,所以我复制了脚本,为Python 3.1.1更新了脚本,并运行了它们。他们工作得很好

然后我做了一些修改。我的目标是做一些简单的事情:

  • 客户端pickle一个整数并将其发送到服务器
  • 服务器接收pickle整数,取消pickle,将其加倍,然后pickle并将其发送回客户端
  • 客户机接收pickle(和double)整数,取消pickle并输出它
  • 这是服务器:

    import pickle
    import socket
    import threading
    
    class ClientThread(threading.Thread):
        def __init__(self, channel, details):
            self.channel = channel
            self.details = details
            threading.Thread.__init__ ( self )
    
        def run(self):
            print('Received connection:', self.details[0])
            request = self.channel.recv(1024)
            response = pickle.dumps(pickle.loads(request) * 2)
            self.channel.send(response)
            self.channel.close()
            print('Closed connection:', self.details [ 0 ])
    
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('', 2727))
    server.listen(5)
    
    while True:
        channel, details = server.accept()
        ClientThread(channel, details).start()
    
    这是客户:

    import pickle
    import socket
    import threading
    
    class ConnectionThread(threading.Thread):
        def run(self):
            client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            client.connect(('localhost', 2727))
    
            for x in range(10):
                client.send(pickle.dumps(x))
                print('Sent:',str(x))
                print('Received:',repr(pickle.loads(client.recv(1024))))
    
            client.close()
    
    for x in range(5):
        ConnectionThread().start()
    
    服务器运行正常,当我运行客户机时,它成功连接并开始发送整数,并按预期加倍接收它们。但是,它很快就会发现:

    Exception in thread Thread-2:
    Traceback (most recent call last):
      File "C:\Python30\lib\threading.py", line 507, in _bootstrap_inner
        self.run()
      File "C:\Users\Imagist\Desktop\server\client.py", line 13, in run
        print('Received:',repr(pickle.loads(client.recv(1024))))
    socket.error: [Errno 10053] An established connection was aborted by the softwar
    e in your host machine
    
    服务器继续运行,接收连接正常;只有客户端崩溃。这是什么原因造成的

    编辑:我让客户机使用以下代码:

    import pickle
    import socket
    import threading
    
    class ConnectionThread(threading.Thread):
        def run(self):
            for x in range(10):
                client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                client.connect(('localhost', 2727))
                client.send(pickle.dumps(x))
                print('Sent:',str(x))
                print('Received:',repr(pickle.loads(client.recv(1024))))
                client.close()
    
    for x in range(5):
        ConnectionThread().start()
    

    然而,我仍然不明白发生了什么。这不就是多次打开和关闭插座吗?不应该有时间限制吗(你不应该在关闭套接字后很快就打开它)?

    你的客户端现在是正确的-你想打开套接字发送数据,接收回复,然后关闭套接字

    错误原始错误是由服务器在发送第一个响应后关闭套接字引起的,这导致客户端在尝试在同一连接上发送第二条消息时收到连接关闭消息

    然而,我还是不明白 发生什么事。这难道不公平吗 打开和关闭插座 多少次

    对。这是可以接受的,即使不是最高性能的做事方式

    难道没有时间吗 限制(你不应该 很快就能打开插座 关闭它

    您可以随心所欲地快速打开客户端套接字,因为每次打开套接字时,您都会得到一个新的本地端口号,这意味着连接不会受到干扰。在上面的服务器代码中,它将为每个传入连接启动一个新线程

    每个IP连接有4个部分(源地址、源端口、目标地址、目标端口),并且这个四元组(众所周知)必须永远更改连接。除了源端口之外的所有东西都是为客户机套接字修复的,所以操作系统会为您更改

    打开服务器套接字更麻烦-如果您想快速打开新的服务器套接字,您的

    server.bind(('', 2727))
    

    在上面,您需要阅读SO_REUSEADDR。

    代码中有一些明显的错误,似乎假设一方的一个发送调用会导致另一方的一个recv调用,这可能不是真的,TCP是一种流协议,它不是面向消息或数据包的。不确定这与错误消息有什么关系。@leeroy我显然是个新手,所以我完全愿意接受批评。您似乎建议我不应该使用TCP,因为它是面向流的,而不是面向数据包的;但是,难道不能将一个数据包简单地表示为一个非常短的数据流吗?我知道这不是它应该如何使用,但这只是为了测试;显然,我打算跨越比单个整数多得多的数据。@leeroy(继续)我的目标是实现这样的东西:仅在Python中。您可以在tcp之上构建自己的“数据包”/记录。e、 g.发送1个数字,后跟换行符。然后,接收端可以读取行。1行=您将知道您已经读取了1个数字。您的服务器只读取一个请求并发送一个响应。因此,要么从客户机中删除该循环,要么将其添加到服务器处理程序中。您还需要一些适当的异常和流结束处理,以及服务器端的读取超时。