为什么主机会中止连接?

发布于 2024-08-05 22:12:15 字数 2721 浏览 2 评论 0原文

我正在自学 Python 网络,我记得当我自学线程时,我遇到了 此页面,因此我复制了脚本,将其更新为 Python 3.1.1 并运行它们。他们工作得很好。

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

  1. 客户端挑选一个整数并将其发送到服务器。
  2. 服务器接收到腌制的整数,将其取消腌制,将其加倍,然后腌制它并将其发送回客户端。
  3. 客户端接收经过腌制(并加倍)的整数,将其取消腌制并输出。

这是服务器:

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()

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

I'm teaching myself Python networking, and I recalled that back when I was teaching myself threading, I came across this page, so I copied the scripts, updated them for Python 3.1.1 and ran them. They worked perfectly.

Then I made a few modifications. My goal is to do something simple:

  1. The client pickles an integer and sends it to the server.
  2. The server receives the pickled integer, unpickles it, doubles it, then pickles it and sends it back to the client.
  3. The client receives the pickled (and doubled) integer, unpickles it, and outputs it.

Here's the server:

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()

And here is the client:

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()

The server runs fine, and when I run the client it successfully connects and starts sending integers and receiving them back doubled as expected. However, very quickly it exceptions out:

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

The server continues to run and receives connections just fine; only the client crashes. What's causing this?

EDIT: I got the client working with the following code:

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()

However, I still don't understand what's going on. Isn't this just opening and closing the socket a bunch of times? Shouldn't there be time limitations to that (you shouldn't be able to open a socket so soon after closing it)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半透明的墙 2024-08-12 22:12:15

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

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

但是我还是不明白
这是怎么回事。这不就是
多次打开和关闭套接字
次数?

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

应该没有时间吧
对此的限制(你不应该
很快就能打开套接字
关闭它)?

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

每个 IP 连接都有 4 个部分(源地址、源端口、目标地址、目标端口),并且这个四元组(众所周知)必须针对每个连接进行更改。除了 source_port 之外的所有内容对于客户端套接字都是固定的,因此这就是操作系统为您所做的更改。

打开服务器套接字比较麻烦 - 如果你想快速打开一个新的服务器套接字,

server.bind(('', 2727))

那么你需要阅读 SO_REUSEADDR 。

Your client is now correct - you want to open the socket send the data, receive the reply and then close the socket.

The error original error was caused by the server closing the socket after it sent the first response which caused the client to receive a connection closed message when it tried to send the second message on the same connection.

However, I still don't understand
what's going on. Isn't this just
opening and closing the socket a bunch
of times?

Yes. This is acceptable, if not the highest performance way of doing things.

Shouldn't there be time
limitations to that (you shouldn't be
able to open a socket so soon after
closing it)?

You can open a client socket as quickly as you like as every time you open a socket you will get a new local port number, meaning that the connections won't interfere. In the server code above, it will start a new thread for each incoming connection.

There are 4 parts to every IP connection (source_address, source_port, destination_address, destination_port) and this quad (as it is known) must change for ever connection. Everything except source_port is fixed for a client socket so that is what the OS changes for you.

Opening server sockets is more troublesome - if you want to open a new server socket quickly, your

server.bind(('', 2727))

Above then you need to read up on SO_REUSEADDR.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文