python 在网络编程中,接受端必须关闭两个套接字吗?

omjgkv6w  于 2023-05-16  发布在  Python
关注(0)|答案(4)|浏览(154)

我刚才提出了一个问题,其中一个答案涉及另一个问题。
也就是说,一般来说,接受端应该创建两个套接字来建立接受端。就像这样:

Python

from socket import *
sockfd = socket(...)
# ...
client_sockfd, addr = sockfd.accept()
# ...
client_sockfd.close()
sockfd.close()

C语言

int sockfd, client_sockfd;
sockfd = socket(...);
// ...
client_sockfd = accept(sockfd, ...);
// ...
shutdown(client_sockfd, 2);
shutdown(sockfd, 2);
close(client_sockfd);
close(sockfd);

那么我们可以跳过创建client_sockfd变量的任务吗?就像这样:

Python

sockfd = socket(...)
# ...
sockfd, addr = sockfd.accept()
# ...
sockfd.close()

C语言

int sockfd;
struct sockaddr_in server, client;
socklen_t client_size = sizeof(client);
sockfd = socket(...);
// ...
sockfd = accept(sockfd, (struct sockaddr *)&client, &client_size);

或者可以是这样的:

Python

sockfd = socket(...)
# ...
client_sockfd, addr = sockfd.accept()
sockfd.close()
# ...
client_sockfd.close()

C语言

int sockfd = socket(...);
int client_sockfd;
// ...
client_sockfd = accept(sockfd, ...);
shutdown(sockfd, 2);
close(sockfd);
// ...
shutdown(client_sockfd, 2);
close(client_sockfd);

如上面的代码所示,我们是否可以只使用一个套接字来完成整个网络编程的接受端?这有什么问题吗?(至少我自己写这样的程序没有任何问题)

pdkcd3nj

pdkcd3nj1#

您总是创建两个套接字:服务器套接字和第一接受的客户端套接字。当你关闭它是由你。
在Python中使用相同的名称仍然会关闭服务器套接字(最终),因为对象引用计数为零,但在C中会泄漏套接字。

kwvwclae

kwvwclae2#

那么我们可以跳过创建client_sockfd变量的任务吗?
对于TCP等面向连接的协议,不需要。在这种服务的接收端涉及的两个套接字是不同类型的,并且服务于不同的目的,两者都是必需的。
通过socket()函数创建并与accept()函数一起使用的套接字(在C中)通常称为“服务器套接字”。它的工作是等待传入的连接请求,当它接受一个连接请求时,准备一个端点与该请求的远程对等体进行通信。结果端点由 * 第二个 *(以及第三个和第四个...)套接字表示,通过成功调用accept()获得。
您使用服务器套接字来接受连接,可能同时有多个活动连接,并且您使用其他每个连接(如果您愿意,可以称为“对等套接字”)与特定的客户端通信。关闭对等套接字将终止与关联的远程对等方的连接。关闭服务器套接字会使系统停止在其地址/端口接受新连接。
您提出了以下备选方案:

int sockfd;
struct sockaddr_in server, client;
socklen_t client_size = sizeof(client);
sockfd = socket(...);
// ...
sockfd = accept(sockfd, (struct sockaddr *)&client, &client_size);

这在技术上并没有错,但是一旦你将accept()的结果赋给变量sockfd,你就不能再访问服务器套接字了(假设你没有将它的文件描述符存储在另一个变量中,这就没有意义了)。这是资源泄漏。此外,它还阻止您在指定的地址/端口接受任何后续连接。在进程终止之前(如果终止的话),您甚至不能为该端口创建新的服务器套接字,因为现有的套接字会碍事。
所有这些对于面向数据报的套接字都是不同的--没有到accept()的连接,并且对于这样的协议,服务器套接字和对等套接字之间没有固有的区别。但是根据示例代码中accept()调用的外观,这不是您要问的问题。

oiopk7p5

oiopk7p53#

我不确定是否有“问题”,但似乎有必要解释一下这里发生了什么:

当你调用sockfd.accept()时,它会阻塞,直到有连接进来。当一个套接字进入时,它返回“代表”连接的 * 另一个 * 套接字,可以用来发送和接收连接上的数据。多次调用socket.close()的原因是,在第一个示例中,client_sockfd.close() * 只关闭连接 *。您仍然可以再次调用sockfd.accept()来接收另一个连接,许多套接字服务器在while循环中使用socket.accept()。调用sockfd.close()将关闭sockfd,通常是在不需要进一步连接(调用sockfd.accept())时。

mf98qq94

mf98qq944#

在你的第一个例子中

from socket import *
sockfd = socket(...)
# ...
client_sockfd, addr = sockfd.accept()
# ...
client_sockfd.close()
sockfd.close()

sockfd是侦听器的描述符。它可以重复使用。关闭client_sockfd后,您可以再次accept
例如:

from socket import *
sockfd = socket(...)
while not is_finished:
   client_sockfd, addr = sockfd.accept()
   # ...
   client_sockfd.close()
sockfd.close()

您可以accept多个套接字(到不同的fd变量中),并与多个客户端进行对话。然而,这需要一些并发编程。

相关问题