私は接続のためにタイムアウトを実装する必要があるソケットクライアントを構築しています。ソケット接続を切り離されたスレッドから中止する
すべてのトランザクションで開始され、トランザクション完了時にキャンセルされる分離されたスレッドで単純なタイマーを使用することを考えています。この同じ手法は、異なるタイムアウトを使用するプロトコル制御に使用されます。タイマーのソケットがエラーで中止することを強制的に、「接続」操作をキャンセルされていません閉会
#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
を分離スレッドからエラーで中止する方法を教えてください。
すべてのプラットフォームで、単にソケットを閉じるだけで 'connect()'が中断されるわけではありません。 –
@RemyLebeau私はそれが何も知らない。それは時々運が起こるかもしれませんが、文字通り保証することは不可能です。(通常の 'socket'、' connect'、 'close' APIだけでは、文字通り実行できません。アトミックな"接続してからロックを解除する "機能などの追加機能を持つAPIが必要です)。 –
@DavidSchwartz Windowsソケットを閉じることによって 'connect()'が打ち切られるようにします。 –