gpt4 book ai didi

linux - 连接到你自己(并占用一个端口号)

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:30:44 26 4
gpt4 key购买 nike

我们遇到过这样一种情况:应用程序显然通过系统分配的端口号“半连接”到自身,并在 Linux(尤其是 Centos 6.4)上“卡住”。

情况如下:

(python)应用程序正在尝试连接到某个服务,假设 IP 地址为 192.168.1.201:8081。由于某种原因,分配的传出端口是 8081。连接成功但套接字上没有进一步的事件,因为它没有真正连接,而是连接了一半(我的猜测是只完成了一半的握手,Linux 正在做其余的在后台提高并行性)。套接字上的读取语句挂起,等待连接的其余部分完成。

这是一个简单的 C++ 程序,可以重现该问题。使用您正在运行的主机的 IP 地址运行它。这是奇特的,因为我们将连接套接字绑定(bind)到一个端口(这是合法的),然后连接到相同的地址和端口而不会生成错误消息,没有“监听”,并且读取挂起。

./foo 192.168.1.201 Connected...going to read...'

ss -na ESTAB 0 0 192.168.1.201:8081 192.168.1.201:8081

如果你终止程序,套接字进入时间等待:

TIME-WAIT 0 0 192.168.1.201:8081 192.168.1.201:8081

问题是:系统分配的端口会发生这种情况吗?您能否进入出站地址/端口以某种方式最终匹配​​目标地址/端口和系统死锁的状态?这似乎就是我们所看到的。

谢谢,

-- 迈克

程序:

#include <assert.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
int ret;
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
struct sockaddr_in sa_loc;

if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}

memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}

memset(&sa_loc, 0, sizeof(struct sockaddr_in));
sa_loc.sin_family = AF_INET;
sa_loc.sin_port = htons(8081);
sa_loc.sin_addr.s_addr = inet_addr(argv[1]);

ret = bind(sockfd, (struct sockaddr *)&sa_loc, sizeof(struct sockaddr));

if (ret != 0) {
perror("bind");
exit(1);
}

memset(&serv_addr, '0', sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8081);

if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}

ret = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (ret != 0) {
perror("connect");
exit(1);
}

printf("Connected...going to read...\n"); fflush(stdout);

while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0) {
recvBuff[n] = 0;
printf("%s", recvBuff); fflush(stdout);
}

if(n <= 0) {
perror("read");
exit(1);
}

return 0;
}

最佳答案

通过将套接字绑定(bind)到一个端口,然后连接到同一个端口,您建立了一种套接字与其自身的环回连接。

Can this happen with system assigned ports?

不,它不能,因为connect(3) promise :

If the socket has not already been bound to a local address, connect() shall bind it to an address which, unless the socket's address family is AF_UNIX, is an unused local address.

这个未使用的本地地址 永远不会与正在运行的服务器 套接字绑定(bind)的地址相同。另外,如果该端口的服务器已经运行,则客户端中的 bind() 不会成功。

Can you get into a state where somehow the outbound address/port ends up matching the destination address/port and the system deadlocks?

如果我们以这种方式明确编程,通过绑定(bind)到我们随后连接到的同一个端口,我们只能进入观察状态。此外,系统 不会死锁,只有应用程序阻塞,很简单,因为它调用 read(),等待从未写入的数据。

关于linux - 连接到你自己(并占用一个端口号),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27708570/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com