WSAConnectByName()
を使用してアドレスに接続しようとしています。しかし、それはtimeout
パラメータを無視したようです。私の代わりに、タイムアウトで失敗の、(ローカルIPアドレスなど)が存在しないアドレスを使用する場合、WSAConnectByName timeout
SOCKET ConnSocket = INVALID_SOCKET;
int iResult;
BOOL bSuccess;
SOCKADDR_STORAGE LocalAddr = {0};
SOCKADDR_STORAGE RemoteAddr = {0};
DWORD dwLocalAddr = sizeof(LocalAddr);
DWORD dwRemoteAddr = sizeof(RemoteAddr);
ConnSocket = socket(AF_INET, SOCK_STREAM, 0);
if (ConnSocket == INVALID_SOCKET){
wprintf(L"socket failed with error: %d\n", WSAGetLastError());
return INVALID_SOCKET;
}
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
bSuccess = WSAConnectByName(ConnSocket, NodeName,
PortName, &dwLocalAddr,
(SOCKADDR*)&LocalAddr,
&dwRemoteAddr,
(SOCKADDR*)&RemoteAddr,
(struct timeval *)&tv,
NULL);
if (!bSuccess){
wprintf(L"WsaConnectByName failed with error: %d\n", WSAGetLastError());
closesocket(ConnSocket);
return INVALID_SOCKET;
}
:ここ
は、MSの例から(ほんの少しだけ変更された)コードであります他のタイムアウトが発生するまでコードは停止します。
ここで何が起こっているのでしょうか?
'ConnectEx()'は標準的なオーバーラップI/Oを使用しているので、タイムアウトを使うことができます。 'OVERLAPPED'構造体を' ConnectEx() 'に渡す必要があります。そのため、イベントオブジェクトへのハンドルを渡してください。次に、GetOverlappedResult()を呼び出す前に、そのイベントでWaitForSingleObject()を呼び出すことができます。イベントがタイムアウトした場合は、 'CancelIo/Ex()'を使って 'ConnectEx()'操作をキャンセルしてください。もし 'WSAConnectByName()'が内部的にそれをしていないなら、それを追加するように求めるM $に機能要求を送ることを勧めます。 –
@RemyLebeau - もちろん、自分自身が 'ConnectEx' - ' WSAConnectByName'を呼び出し、 'OVERLAPPED'でhEventを作成/使用するとタイムアウトを使用することができます。 'GetOverlappedResult()'このイベントではまさにこのイベントを待っているので、単に 'WaitForSingleObject'(タイムアウトで)を' GetOverlappedResult() 'を呼び出すことなく簡単に行うことができます。しかし、私は最高の解決策(私の見解では) - 本当に非同期的に 'ConnectEx'を使うことを意味します。 IOCPをソケットに直接バインドするか(または 'BindIoCompletionCallback'を使用する)、まったく待ちません。 'ERROR_IO_PENDING'はOKです。私たちのコールバックは – RbMm
@RemyLebeauと呼ばれています - はい、最新の勝利10(1607) - まだ同じコード 'ConnectEx(*)/ if(GetLastError()== ERROR_IO_PENDING)/ GetOverlappedResult(*);' 'WSAGetOverlappedResult' - より正確に言えば、 – RbMm