В тесте ниже получаю ошибочное присоединение сокетов на TCP порты 50020 ... 50029, при условии, что никто эти порты не открывает на прослушивание. Ошибку получаю только под Windows 7. В течении суток работы теста все сокеты будут присоединены. Тестировал на чистой Windows 7 под VMWare. TCPView (SysInternals) говорит, что соединение произведено на удалённый адрес "localhost" 50020... 50029 (процесса который бы их слушал в списке нет). Поискал в Интернете — никто о такой проблеме не пишет.
Минимальный тест (см. ниже) создавал как консольный проект под C++ Builder 2007, собирал как MultyThread, C++. Тестовая OS: чистая Windows 7 32 разряда (NT 6.1 7600 Enterprise). Пробовал также собирать под MSVC Studio 2005 — результат тот же.
Что-то делаю не так? Возможно это уже известная проблема? Заранее спасибо.
Листинг:
//---------------------------------------------------------------------------
#include <windows.h> // MessageBox
#include <process.h> // beginThreadEx
#include <stdio.h> // printf
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma link "ws2_32.lib"
//---------------------------------------------------------------------------
#pragma argsused
//---------------------------------------------------------------------------
// Декларации:
void showInfo(char* apInfo);
void logOut(char* apInfo);
unsigned __stdcall threadFunc(void* apThread);
int tryConnect(int anPortNum);
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
WSADATA wsaData;
int nResult = -1;
nResult = ::WSAStartup(MAKEWORD(2, 0), &wsaData);
if(nResult)
{
showInfo("Ошибка WSAStartup()");
}
else
{
showInfo("WSA Started");
}
// Создадим 10 нитей:
HANDLE hThread = NULL;
unsigned int uiThreadID = 0;
int* pnPort = NULL;
for(int i=0; i<10; i++)
{
// Будут лики, но это сейчас не важно
pnPort = new int;
if(pnPort)
{
// Порты, куда коннектимся с 50020 до 50029
*pnPort = 50020 + i;
}
hThread = (HANDLE)_beginthreadex(
NULL,
1024*1024,
&threadFunc,
(void*)pnPort,
0,
&uiThreadID);
if(hThread == INVALID_HANDLE_VALUE)
{
showInfo("Ошибка создания нити");
continue;
}
}
// Рисовать нормальное завершение нитей не охото. По Ctrl+C если что можно убить.
for(;;)
{
::Sleep(INFINITE);
}
return 0;
//---------------------------------------------------------------------------
unsigned __stdcall threadFunc(
void* apThread)
for(;;)
{
tryConnect(*((int*)apThread));
::Sleep(1000);
}
};
//---------------------------------------------------------------------------
int tryConnect(
int anPortNum)
// Готовим структуру:
struct sockaddr_in sockaddr;
::ZeroMemory(&sockaddr, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.S_un.S_addr = ADDR_ANY;
{
const char* szHostName = "localhost";
ULONG ulIP = ADDR_ANY;
// тогда по буквам но это медленнее
struct hostent* pbuf_host = NULL;
pbuf_host = ::gethostbyname(szHostName);
if(!pbuf_host)
{
showInfo("pbuf_host is NULL");
return -1;
}
ulIP = *((ULONG*)pbuf_host->h_addr_list[0]);
sockaddr.sin_addr.S_un.S_addr = ulIP;
}
{
sockaddr.sin_port = ::htons(anPortNum);
}
SOCKET sSocket = INVALID_SOCKET;
sSocket = ::WSASocket(
AF_INET,
SOCK_STREAM,
IPPROTO_TCP,
NULL,
0,
WSA_FLAG_OVERLAPPED);
if(sSocket == INVALID_SOCKET)
{
DWORD dwErrcode = WSAGetLastError();
showInfo("Ошибка создания сокета");
return -3;
}
// Пытаемся присоединится:
int nResult = -1;
nResult = ::connect(
sSocket,
(const struct sockaddr*)&sockaddr,
sizeof(sockaddr));
if(nResult)
{
DWORD dwErrcode = WSAGetLastError();
// Выводить не буду - это норма
//showInfo("Ошибка коннекта");
logOut("Error connecting");
::closesocket(sSocket);
return -5;
}
else
{
//AnsiString strInfo = "Соединение установлено! Порт: " + IntToStr(anPortNum);
char szInfo[128];
sprintf(szInfo, "Соединение установлено! Порт: %d", anPortNum);
showInfo(szInfo);
::closesocket(sSocket);
}
return 0;
};
//---------------------------------------------------------------------------
void showInfo(char* apInfo)
logOut(apInfo);
::MessageBox(NULL, apInfo, "Информация", MB_OK);
};
//---------------------------------------------------------------------------
void logOut(char* apInfo)
SYSTEMTIME sysTime;
::GetSystemTime(&sysTime);
printf("%d:%d:%d.%d %s \r\n",
sysTime.wHour,
sysTime.wMinute,
sysTime.wSecond,
sysTime.wMilliseconds,
apInfo);
};
//---------------------------------------------------------------------------