Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: CAsyncSocket  (Прочитано 21490 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Tuborg
Команда клуба

ee
Offline 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)

Где туплю?
Записан
Джон
просто
Администратор

de
Offline 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."
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #2 : 11-12-2007 14:12 » 

Нуль
Записан
Джон
просто
Администратор

de
Offline 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."
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #4 : 12-12-2007 12:48 » 

ГетЛастЕррор даёт 10038. То бишь применяем сокетный метод не на сокете.... не понимаю ладно... пробую иначе -
DataStreamUDPServer.Bind(5001); (одна из форм позволяет задать только номер UDP порта)

Ошибка та же...

Ладно... пробую перед этим сделать Create для этого сокета.... ошибка 10038
Записан
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #5 : 13-12-2007 15:52 » 

Так в чём трабла то? ошибка осталась!
Записан
Джон
просто
Администратор

de
Offline 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."
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #7 : 13-12-2007 20:00 » 

По порядку, хм...

Решил я углубиться в MFC.
Раньше везде в своих клиентских прогах пользовал тип SOCKET и функции recvfrom, bind и прочее... всё работало хорошо...

Теперь вот хочу заменить SOCKET на MFCшную оболочку CAsyncSocket и его методы.
Первое что не получается - не могу сделать Bind. GetLastError возвращает 10038, согласно RTFMу =) это означает что я использую сокетные методы не на сокете.
Сокет я создаю статически и локально (в нитке опроса сокета) : CAsyncSocket DataStreamUDPServer
(в первом посте написано как я создаю сокет и пытаюсь ему сделать Bind)
Записан
lag
Участник

ru
Offline 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
Участник

ru
Offline 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);
}
Записан
Tuborg
Команда клуба

ee
Offline Offline

« Ответ #10 : 15-12-2007 10:38 » 

Спасибо... то что надо!
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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-ю попытку, то тоже более или менее красиво - он отваливается по таймауту сам.

как же бороться с "зависанием" клиента (вторая попытка) или как всё таки вырубить слушалку ?
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 12-01-2009 06:26 » 

(самое простое напрашивающееся) закрыть слушающий сокет? Улыбаюсь Хотя это как-то невежливо Улыбаюсь Ведь существует на системном уровне (правда, не помню, у каких ОС) защита от DoS-атак, основанная на том, что система имеет ограниченную очередь запросов.
« Последнее редактирование: 12-01-2009 06:31 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 12-01-2009 06:35 » 

закрывать неудобно, хотя надо подумать )

дело в том, что объект должен сам себя закрыть и создать заново, как это провернуть то ? )
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 12-01-2009 06:57 » 

вроде получилось )

когда не должны больше подключаться, закрываю this->Close() сервер , пересоздаю  Create , но Listen не вызываю.
Когда один из клиентов отключается, вызываю Listen(1)


получился прикольный класс с сервером и очередью клиентов - всё в кучу ))) Красота
« Последнее редактирование: 12-01-2009 06:59 от Алексей1153++ » Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 12-01-2009 07:02 » 

Я вот тут подумал. А почему у тебя Listen(1)? Не проще сделать Listen(n), и делать accept только если уже подключено меньше m клиентов?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 12-01-2009 07:05 » 

Вад, я же написал, что без ассепта клиент фигнёй страдает, Listen(1...5) видать создаёт очередь сокетов где то в глубине - к ним и подключаются клиенты, и если им не отвечать, они "висят"
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 05-12-2009 11:13 » 

снова вопрос по CASyncSocket

имеется клиент (К) , сервер (С) и серверная пара для клиента (Ск)

устанавливаю TCP соединение. Затем начинаю непрерывным потоком гнать данные с клиента на сервер (К->Ск)

в один прекрасный момент метод Send клиента возвращает SOCKET_ERROR, а GetLastError - WSAEWOULDBLOCK.
Тут я должен чуточку переждать и возобновить отправку. Но по некоторым причинам в Ск перестаёт вызываться OnReceive, поэтому данные не считываются автоматом. Попробовал "пнуть", искусственно в этот момент OnReceive на сервере - данные считались, и далее также продолжила автоматом вызываться OnReceive

Как предполагаю - переполнился приёмный системный буфер Ск, после чего отрубилось извещение о непустом буфере приёма. Когда пинаю - извещение начинает снова приходить. Это так и нужно - пинать, либо есть какое то штатное средство ?
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 05-12-2009 17:05 » 

заметил, что в качестве пинка срабатывает также AsyncSelect(m_LastSetEventMask), где у меня m_LastSetEventMask - это последний установленный набор событий.

Вставил сей вызов в самый конец функции OnReceive() , больше затыков вроде не происходит. То есть, где то сбрасывается флаг FD_READ (а может и ещё какие?) но это не в моём коде, проанализировал на эту тему.
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines