gpt4 book ai didi

c++ - 套接字连接从分离的线程中止

转载 作者:行者123 更新时间:2023-11-27 22:51:41 24 4
gpt4 key购买 nike

我正在构建一个套接字客户端,我需要在其中实现连接、读取、写入超时以及协议(protocol)本身的超时(缺少答案等)。

我正在考虑在独立线程中使用一个简单的计时器,该计时器将在每次交易时启动,然后在交易完成时取消。同样的方法将用于使用不同超时的协议(protocol)控制。

为了测试,我做了以下简单的代码:

#include <string>
#include <sstream>
#include <map>
#include <iostream>
#include <cstring>
#include <thread>

#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#endif

#include <stdio.h>
#include <stdlib.h>

bool timerOn = false;
int currentSocket = 0;


void Timer(int seconds)
{
int tick = seconds;

while (tick > 0)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
tick--;
}

if (timerOn)
close(currentSocket);
}

void StartTimer(int seconds)
{
timerOn = true;
std::thread t(&Timer, seconds);
t.detach();
}

void StopTimer()
{
timerOn = false;
}


void Connect(std::string address, int port)
{
struct addrinfo hints;
struct addrinfo *result = NULL;
struct addrinfo *rp = NULL;
int sfd, s;

std::memset(&hints, 0, sizeof(struct addrinfo));

hints.ai_family = AF_UNSPEC; /* Allow IPV4 or IPV6 */
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;

std::string portStr;
portStr = std::to_string(port);

s = getaddrinfo(address.c_str(), portStr.c_str(), &hints, &result);

if (s != 0)
{
std::stringstream ss;
ss << "Cannot resolve hostname " << address << gai_strerror(s);
throw std::runtime_error(ss.str());
}

for (rp = result; rp != NULL; rp = rp->ai_next)
{
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

if (sfd == -1)
continue;

StartTimer(10);
int sts = connect(sfd, rp->ai_addr, rp->ai_addrlen);
StopTimer();

if (sts == 0)
break;

close(sfd);
}

freeaddrinfo(result); /* Object no longer needed */

if (rp == NULL)
{
std::stringstream ss;
ss << "Cannot find server address at " << address << " port " << port;
throw std::runtime_error(ss.str());
}

currentSocket = sfd;
}


int main()
{
try
{
Connect("192.168.0.187", 9090);
std::cout << "Connected to server. Congrats!!!" << std::endl;
}
catch (std::exception& ex)
{
std::cout << "Error connecting to server. Aborting." << std::endl;
std::cout << ex.what() << std::endl;
}
}

在计时器上关闭套接字并不会取消“连接”操作,而是强制它因错误而中止。我也试过 shutdown(sfd, SHUT_RDWR); 但没有成功...

我的方法无效吗?为什么它不起作用?

如何强制 connect 因分离线程的错误而中止?

最佳答案

Closing the socket on timer is not canceling the 'connect' operation, forcing it to abort with error.

哇哦!你绝对不能那样做。当您关闭套接字时,无法知道线程实际上在 connect 中被阻塞(而不是即将调用 connect)。在一个线程中释放资源,而另一个线程正在或可能正在使用它是灾难的根源。

想象一下:

  1. 一个线程即将调用connect,因此它安排了一个超时。

  2. 超时到期,套接字关闭。

  3. 某些库中的线程出于某种原因创建了一个新的套接字以供使用,并获得了相同的套接字描述符。

  4. 即将调用 connect 的线程终于得到调度并调用 connect —— 连接库的套接字!灾难。

你有两个选择:

  1. 使用非阻塞connect操作。

  2. 使用信号之类的东西来中断调用 connect 的线程。

但我想知道你为什么要打扰。为什么需要中止连接?如果在超时之前连接未成功,您需要执行其他操作,请继续执行。

关于c++ - 套接字连接从分离的线程中止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36634371/

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