Подскажите по винсоку. Делаю Код (Text): // Sleep(1000) ; <- смотрите ниже //========================================================================== // Открываем сокет //========================================================================== Sock:=Socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if Sock = SOCKET_ERROR then Exit; //========================================================================== // CloseSocket будет закрывать сокет грубо и ждать пока не закроется //========================================================================== Linger.l_onoff := 1; Linger.l_linger:= 0; if setsockopt(Sock, SOL_SOCKET, SO_LINGER, @Linger, sizeof(Linger))<>0 then begin closesocket(Sock); Exit; end; //========================================================================== // Разблокируем сокет //========================================================================== Block:=1; if ioctlsocket(Sock,FIONBIO,Block)<>0 then begin _closesocket(Sock); Exit; end; //========================================================================== // Коннектимся к хосту //========================================================================== AddrIn.sin_addr.s_addr :=inet_addr(sHost); AddrIn.sin_family :=AF_INET; AddrIn.sin_port :=htons(aPorts[iPort]); connect(Sock,AddrIn,sizeof(AddrIn)); if WSAGetLastError <> WSAEWouldBlock then begin _closesocket(Sock); Continue; end; //========================================================================== // Блокируем сокет //========================================================================== Block:=0; if ioctlsocket(Sock,FIONBIO,Block)<>0 then begin _closesocket(Sock); Exit; end; //========================================================================== // Ждем коннекта по таймауту 10 сек //========================================================================== FD_Zero(SetW); FD_Set(Sock,SetW); FD_Zero(SetE); FD_Set(Sock,SetE); timeval.tv_sec := 10; timeval.tv_usec:= 00; TimeOut := select(0,nil,@SetW,@SetE,@timeval); Всё работает как надо, но только в двух случаях. Либо этот код прогоняется 1 раз, либо для этого кода создается отдельный тред. У меня этот код в цикле. Первый раз цикл отрабатывает нормально, а все последующие итерации connect возвращает TimeOut = 0. Я уже и shutdown делал, и после shutdown селект пытался юзать и SO_LINGER коментил и после closesocket снова вызывал select. Всё равно все последующие итерации connect не работает. Помогло только одно, перед началом следующей итерации ставлю Sleep(1000), вот тогда всё нормально, все итерации конекты проходят нормально. Мне не понятно в чем дело, я ведь выставил SO_LINGER чтобы сокет сразу же закрывался, да и какая разница вообще, ведь если даже сокет занят, то функция socket должна вернуть свободный, но вот без Sleep оно почему то не работает. Я конечно могу оставить и так, но это как то не по дзенски, должны жить быть какие то легальные методы. Переколупал разные сорсы, везде, где есть подобный код - вижу Sleep в пределах 1000 (обычно чуть меньше), сталобыть я не первый такой.
PE_Kill, ты хочешь асинхронный connect()? Это просто так не сделать. Есть два варианта: a) отдельный поток и у него очередь (ессно он делает blocking connect()) b) IO completion ports - в Server 2003 и Vista есть ConnectEx - overlapped версия
s0larian я не хочу асинхронный коннект. Я хочу коннект по таймауту. Для этого я разблокирую сокет вызываю асинхронно коннект и селектом жду пока не выйдет время либо пока не приконектимся, потом снова блокируем сокет ну дальше уже не интересно. Код приведенный выше прекрасно работает, либо коннектится либо отваливается по таймауту, но это только первый раз, после закрытия сокета и создания нового следующий connect всегда отваливается по таймауту. Работает только если после закрытия сокета вызвать Sleep(1000) и потом только снова всё прогонять. Вот и интересует почему так. Т.е. например тот код выше исполняется в отдельном потоке в цикле, отрабатывает без Sleep(1000) один раз а потом всегда connect валится в таймаут.
Эта, у тебя тут ошибки, кажется: 1) в вызове socket() надо иметь IPPROTO_TCP 2) socket поставь в blocking mode перед вызовом closesocket() 3) поставь SO_DONTLINGER 4) tv_sec в секундах 5) в select() нужно послать кол-во sockets
Поставил IPPROTO_TCP действительно итерации стали проходить медленнее. И, о чудо, на второй итерации connect тоже прошел удачно! Но дальше всё повторилось, причем чем выше итерация тем быстрее пролетает connect, на 1000ной итерации connect занимает милисекунды а потом вообще вылетает программа. Поставил сразу после connect ничего не изменилось Оно и так по умолчанию стоит я мне надо чтобы closesocket ждал пока сокет окончательно не закроется, а вообще проверял и так и так ниче не меняется. У меня и так в секундах Это где такой параметр? Структуры передаваемые и так содержат количество сокетов, первый параметр просто заглушка.
что-то у тебя косячит... дельфизмы? Вот твой пример на С++ - всё пашет: Код (Text): namespace { bool Connect(SOCKET sock, const std::string &host, uint16 port) { addrinfo aiHints, *aiList = NULL; memset(&aiHints, 0, sizeof(aiHints)); aiHints.ai_family = AF_INET; aiHints.ai_socktype = SOCK_STREAM; aiHints.ai_protocol = IPPROTO_TCP; // If the call succeeds, the aiList variable will hold a linked list // of addrinfo structures containing response information about the host if (getaddrinfo(host.c_str(), base::sprintfT<char>("%d", port).c_str(), &aiHints, &aiList) != 0) return false; if (connect(sock, aiList->ai_addr, sizeof(*aiList->ai_addr)) != SOCKET_ERROR) return false; return GetLastError() == WSAEWOULDBLOCK; } int32 Wait(SOCKET sock, uint32 seconds) { fd_set set; FD_ZERO(&set); FD_SET(sock, &set); timeval timeout = { 4, 0 }; return select(1, NULL, &set, NULL, &timeout); } int UserMain(int argc, char *argv[]) { base::Socket::InitializeWinsock(); uint32 timeout = 0, connected = 0, error = 0; for (uint32 i = 0; i < 1000; ++i) { // Create a non-clocking socket SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) return 1; ULONG option = 1; if (ioctlsocket(sock, FIONBIO, &option) != 0) return 1; // Initiate a connection if (!Connect(sock, "localhost", 80)) return 1; // Wait int32 res = Wait(sock, 4); switch (res) { case 0: timeout++; break; case 1: connected++; break; default: error++; } option = 0; if (ioctlsocket(sock, FIONBIO, &option) != 0) return 1; closesocket(sock); } std::cout << "Done: connected=" << connected << ", timeout=" << timeout << ", error=" << error << std::endl; return 0; } } int main(int argc, char *argv[]) { int rv = UserMain(argc, argv); #ifdef _DEBUG _CrtMemDumpAllObjectsSince(NULL); #endif return rv; }