Tuborg
Команда клуба
Offline
|
|
« : 11-12-2007 12:35 » |
|
Решил на досуге отойти от сишного SOCKET к MFCшному CAsyncSocket. Но где то туплю, помогите разобраться! Раньше было: SOCKET DataStreamUDPServer; bind(DataStreamUDPServer, (const SOCKADDR*)&data_SocketService, sizeof(data_SocketService));
// создаю нить процесса, в котором: ret=recvfrom(DataStreamUDPServer,tmpArray,DataMsgLength,NULL,(sockaddr*) &from_addr, &from_len)
теперь хочется чтоб вот это работало: CAsyncSocket DataStreamUDPServer;
//(прочёл что на стороне сервера CREATE делать не надо... пробовал и с ним и без него - не выходит)
DataStreamUDPServer.Bind((SOCKADDR*)&socket, sizeof(socket));
// создаю нить процесса, в котором: ret=DataStreamUDPServer.ReceiveFrom(tmpArray, DataMsgLength, (sockaddr*) &from_addr, &from_len);
в последнем случае ret всегда = -1. То бишь SOCKET_ERROR Гляжу в Watch'ах сразу после бинда: DataStreamUDPServer.m_hSocket = 0xFFFFFFFF (т.е. -1) Где туплю?
|
|
|
Записан
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #1 : 11-12-2007 14:07 » |
|
А Bind тебе чего возвращает?
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #3 : 11-12-2007 15:08 » |
|
Та это уже плохо. Нуль значит ошибка. Зафигачивай GetLastError после него.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
|
|
Джон
просто
Администратор
Offline
Пол:
|
|
« Ответ #6 : 13-12-2007 17:48 » |
|
Tuborg, я ща завален работой по самые... нехочу. А ты так сумбурно всё излагаешь, что я честно говоря нифига не понимаю даже как тебе помочь. В голове я все ошибки тоже не держу. И 10038 мне ни о чём ни говорит.
У тебя какой-нить примерчик есть? С codegur/codeproject? Или с чего ты начал? Давай попорядку.
|
|
|
Записан
|
Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома. "Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash "Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman "All science is either physics or stamp collecting." Ernest Rutherford "Wer will, findet Wege, wer nicht will, findet Gründe."
|
|
|
|
lag
Участник
Offline
|
|
« Ответ #8 : 15-12-2007 10:10 » |
|
HANDLE g_evReceived; CAsyncSocket sockOut; long e = sockOut.Create(0, SOCK_DGRAM, 0); while (g_fLoop) // Передаем пакеты пока стоит флаг работы { ::SendAnswer(&sockOut, reader, "192.168.10.16", 42012); ::Sleep(2000); if (::WaitForSingleObject(g_evReceived, 1000) != WAIT_TIMEOUT) { // Ответ получен } } // while
........
void CReceiveSocket::OnReceive(int err) { ........ ::SetEvent(g_evReceived); }
|
|
|
Записан
|
|
|
|
lag
Участник
Offline
|
|
« Ответ #9 : 15-12-2007 10:14 » |
|
Да забыл... void SendAnswer(CAsyncSocket *sockOut, WORD dev, CString host, WORD port) { .......... sent = sockOut->SendTo(ans, sizeof(ans), port, host); }
|
|
|
Записан
|
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #11 : 12-01-2009 05:01 » |
|
ещё вопрос по CAsyncSocket (хотя, думаю, это скорее к каким то глубинным процессам относится) если я один раз запустил Listen(1); , то как его остановить, если не нужно больше клиентов подключать ? пока делаю так class CObjectAsyncSocket : public CAsyncSocket { ... }
void CObjectAsyncSocket::OnAccept(int nErrorCode) { //подслушан запрос от клиента if(m_mode==e_server && nErrorCode==0 && ...) { CObjectAsyncSocket* s=0;
//ищем, есть ли ещё свободные места s= .....->CreateNewClient(this);
if(!s) { //свободных мест нету, отпинываем
//вызываем accept вхолостую { CAsyncSocket s_idle; CAsyncSocket::Accept(s_idle,0,0); s_idle.Close(); }
//и вот тут бы хорошо выключить слушалку //...
} else { //подключаем долбящегося ... } } ... ... }
у этого эсть недостаток - сервер можно "занять" бесполезной работой при лавине соединений если холостой accept не делать, то файервол показывает, что клиент установил соединение, хотя непонятно - с чем ? Тут неудобство только со стороны клиента остаётся, но всё равно некрасиво. если совместить холостой ассепт с выключением события FD_ACCEPT AsyncSelect(0|FD_CLOSE); то первая лишняя попытка клиента подключиться заканчивается красиво - отпнули, события отрубили. вторая попытка - опять непонятно куда соединение (в программе точно нигде не подсоединяю, а фаер показывает, да и время в гипертерминале начинает тикать, если им подключаться) если остановить соединение в гипертерминале и сделать 3-ю попытку, то тоже более или менее красиво - он отваливается по таймауту сам. как же бороться с "зависанием" клиента (вторая попытка) или как всё таки вырубить слушалку ?
|
|
|
Записан
|
|
|
|
Вад
|
|
« Ответ #12 : 12-01-2009 06:26 » |
|
(самое простое напрашивающееся) закрыть слушающий сокет? Хотя это как-то невежливо Ведь существует на системном уровне (правда, не помню, у каких ОС) защита от DoS-атак, основанная на том, что система имеет ограниченную очередь запросов.
|
|
« Последнее редактирование: 12-01-2009 06:31 от Вад »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 12-01-2009 06:35 » |
|
закрывать неудобно, хотя надо подумать )
дело в том, что объект должен сам себя закрыть и создать заново, как это провернуть то ? )
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #14 : 12-01-2009 06:57 » |
|
вроде получилось )
когда не должны больше подключаться, закрываю this->Close() сервер , пересоздаю Create , но Listen не вызываю. Когда один из клиентов отключается, вызываю Listen(1)
получился прикольный класс с сервером и очередью клиентов - всё в кучу ))) Красота
|
|
« Последнее редактирование: 12-01-2009 06:59 от Алексей1153++ »
|
Записан
|
|
|
|
Вад
|
|
« Ответ #15 : 12-01-2009 07:02 » |
|
Я вот тут подумал. А почему у тебя Listen(1)? Не проще сделать Listen(n), и делать accept только если уже подключено меньше m клиентов?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #16 : 12-01-2009 07:05 » |
|
Вад, я же написал, что без ассепта клиент фигнёй страдает, Listen(1...5) видать создаёт очередь сокетов где то в глубине - к ним и подключаются клиенты, и если им не отвечать, они "висят"
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 05-12-2009 11:13 » |
|
снова вопрос по CASyncSocket
имеется клиент (К) , сервер (С) и серверная пара для клиента (Ск)
устанавливаю TCP соединение. Затем начинаю непрерывным потоком гнать данные с клиента на сервер (К->Ск)
в один прекрасный момент метод Send клиента возвращает SOCKET_ERROR, а GetLastError - WSAEWOULDBLOCK. Тут я должен чуточку переждать и возобновить отправку. Но по некоторым причинам в Ск перестаёт вызываться OnReceive, поэтому данные не считываются автоматом. Попробовал "пнуть", искусственно в этот момент OnReceive на сервере - данные считались, и далее также продолжила автоматом вызываться OnReceive
Как предполагаю - переполнился приёмный системный буфер Ск, после чего отрубилось извещение о непустом буфере приёма. Когда пинаю - извещение начинает снова приходить. Это так и нужно - пинать, либо есть какое то штатное средство ?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #18 : 05-12-2009 17:05 » |
|
заметил, что в качестве пинка срабатывает также AsyncSelect(m_LastSetEventMask), где у меня m_LastSetEventMask - это последний установленный набор событий.
Вставил сей вызов в самый конец функции OnReceive() , больше затыков вроде не происходит. То есть, где то сбрасывается флаг FD_READ (а может и ещё какие?) но это не в моём коде, проанализировал на эту тему.
|
|
|
Записан
|
|
|
|
|