gpt4 book ai didi

c++ - 处理隧道时,套接字 read() 函数有时从不返回 0

转载 作者:行者123 更新时间:2023-11-30 05:00:42 24 4
gpt4 key购买 nike

if(port == 443){ // https
strcpy(buffer, "HTTP/1.0 200 Connection established\r\n\r\n");
write(client, buffer, strlen(buffer));
tunnel(server, client, buffer);
return;
}

tunnel() 如下所示

void tunnel(int server, int client, char* buffer){
int servercon, clientcon;
int x;
x = fcntl(server, F_GETFL, 0);
fcntl(server, F_SETFL, x|O_NONBLOCK);
x = fcntl(client, F_GETFL, 0);
fcntl(client, F_SETFL, x|O_NONBLOCK);
while(true){
cout << "test" << endl;
clientcon = read(client, buffer, BUFSIZE);
write(server, buffer, clientcon);
servercon = read(server, buffer, BUFSIZE);
write(client, buffer, servercon);
if(???) // This condition
break;
}

close(client);
close(server);
}

我正在尝试在代理服务器接收到 CONNECT 方法时实现隧道。此代码运行良好(成功加载 HTTPS 网站)然而,问题是无法逃脱无限 while() 循环,因为 read() 函数有时永远不会返回 0。

作为中断条件,我尝试了几种选择。

1) servercon == 0(有时 read() 函数从不返回 0)

2) servercon == -1 (Secure connection failed occurs. I don't know why)

3)添加一个变量i作为定时器,i<100000(可以,但是效率太低)

中断条件应该怎么设置?

(使socket非阻塞是必要的,没有它,程序永远停在read()函数。我不知道原因,但是使socket成为非阻塞解决了问题。)

最佳答案

您的 tunnel() 循环完全忽略了 read()write() 的返回值。尝试更像这样的东西:

bool writeAll(int sckt, void *buffer, size_t buflen)
{
char *pbuffer = (char*) buffer;
while (buflen > 0)
{
ssize_t numSent = write(sckt, pbuffer, buflen);
if (numSent < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
continue;
return false;
}
pbuffer += numSent;
buflen -= numSent;
}
return true;
}

...

strcpy(buffer, "HTTP/1.0 200 Connection established\r\n\r\n");
if (writeAll(client, buffer, strlen(buffer)))
tunnel(server, client, buffer);
close(client);
close(server);
return;

...

void tunnel(int server, int client, char *buffer)
{
int maxFD = max(server, client) + 1;
ssize_t numRead;
FD_SET fd;

int x = fcntl(server, F_GETFL, 0);
fcntl(server, F_SETFL, x | O_NONBLOCK);

x = fcntl(client, F_GETFL, 0);
fcntl(client, F_SETFL, x | O_NONBLOCK);

do
{
cout << "test" << endl;

FD_ZERO(&fd);
FD_SET(&fd, server);
FD_SET(&fd, client);

x = select(maxFD, &fd, NULL, NULL, NULL);
if (x < 0) break;

if (FD_ISSET(&fd, client))
{
numRead = read(client, buffer, BUFSIZE);
if (numRead <= 0) break;

if (!writeAll(server, buffer, numRead))
break;
}

if (FD_ISSET(&fd, server))
{
numRead = read(server, buffer, BUFSIZE);
if (numRead <= 0) break;

if (!writeAll(client, buffer, numRead))
break;
}
}
while (true);
}

至于为什么你的读取并不总是像你期望的那样返回 0,这很可能是由于客户端和服务器使用 HTTP keep-alive 在服务器发送响应后保持隧道连接打开,所以客户端可以使用相同的 TCP 连接向同一服务器发送后续请求。在每个 HTTP/S 请求上建立新的 TCP 连接,甚至新的 HTTPS session 都非常耗时并且浪费带宽,因为它涉及 TCP 和 TLS 握手的多次往返。因此 HTTP 1.1 及更高版本的默认行为是保持连接打开,除非任何一方通过 Connection: close header 明确声明需要关闭。

关于c++ - 处理隧道时,套接字 read() 函数有时从不返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50626041/

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