套接字 read() 函数在处理隧道时有时从不返回 0


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

隧道(( 如下所示

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( 服务器Con == -1(发生安全连接失败。我不知道为什么(

3(添加一个变量i作为计时器,i<100000(它有效,但效率太低(

我应该如何设置中断条件?

(使套接字不阻塞是必要的。没有它,程序将永远停止在 read(( 函数处。我不知道原因,但使套接字不阻塞解决了问题。

您的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 establishedrnrn");
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 会话非常耗时且浪费带宽,因为它涉及 TCP 和 TLS 握手的多次往返。 因此,HTTP 1.1 及更高版本的默认行为是保持连接打开,除非任何一方明确表示希望通过Connection: close标头关闭。

最新更新