Поиск:

Ответ в темуСоздание новой темы Создание опроса
> CAsyncSocket и потоки, запутался, кто кого вызывает. 
:(
    Опции темы
Dreamer_0x01
Дата 20.12.2005, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



В классе CAsyncSocket есть переопределяемые функции типа OnAccept, OnReceive и т.д., в которых можно выполнять какие-то свои действия.
А кто их вызывает? Я имею в виду, какой поток вызывает сами эти функции?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 20.12.2005, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата(Dreamer_0x01 @ 20.12.2005, 14:54)
А кто их вызывает? Я имею в виду, какой
поток вызывает сами эти функции?


Переопредели у себя в классе A (class A : public CAsyncSocket) OnAccept, OnReceive, поставь бряк, а потом уже на нем просмтори стек вызовов




--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 20.12.2005, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



А однозначного ответа на это нет что ли, зависит от ситуации?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 20.12.2005, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Так это же (стек вызовов) самое простое решение.
Добавлено @ 16:53
Debug->Windows->Call Stack


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 20.12.2005, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Ясно, щас займемся.
Просто до дебага я еще не скомпилировал ;)


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Coocky
Дата 20.12.2005, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


GUI гуру
****


Профиль
Группа: Участник Клуба
Сообщений: 2879
Регистрация: 16.2.2004
Где: Украина. Запорожь е

Репутация: 25
Всего: 62



Dreamer_0x01
А зачем такие подробности, если не секрет?
Что надо вообщем-то?


--------------------
Верю в смерть после жизни, в любовь после секса ,в крем после бритья smile        
PM ICQ   Вверх
Dreamer_0x01
Дата 21.12.2005, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Мне нужно работу с сокетами запихать в отдельный поток.

и в этом отдельном потоке нужно ожидать приема данных сокетом.
(Принцип простой - я запросил у внешнего устройства пакет данных и должен дождаться его получения).
Фот собственно с ожиданием и возникли проблемы - как быть?
В месте, где нужно ждать приема данных, так и просится создать цыкл какой-либо переменной, с заходом/выходом в критическую секцию, значение которой выставить по переопределяемой функции OnReceive класса сокета.
Вот и думаю - будет работать или нет? Ведь если сокет создает свой поток при инициализации, то все будет нормально. А если эти вункции вызываются тем потоком, в котором создан экземпляр сокета - то мой цикл попросту заснет...


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Romikgy
Дата 21.12.2005, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 2
Всего: 146



Имхо ф-ция
Цитата(Dreamer_0x01 @ 21.12.2005, 13:43)
OnReceive
вызовится только тогда , когда прийдут данные на сокет, зачем здесь поток? Тем более что сокет асинхронный!!!



--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Dreamer_0x01
Дата 21.12.2005, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Функция вызывается не святым духом, а каким-то потоком. Каким? Моим, или каким-то другим, порожденным сокетом? Или оконным? Или главным потоком программы?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Romikgy
Дата 21.12.2005, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 2
Всего: 146



Имхо в стеке будет адресс твоего потока , но инициатором будет система


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Dreamer_0x01
Дата 21.12.2005, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Так, посмотрел в дебаггере, кто вызывает эту функцию, написано, что WinMain. Это чей поток?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Romikgy
Дата 21.12.2005, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 2
Всего: 146



smile Твой


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
JoyEx
Дата 21.12.2005, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Romikgy прав.

Winsock (Ws2_32.dll) через ntdll.dll (NtDeviceIoControlFile, NtReadFile, NtWriteFile, NtCreateFile) обращается в kernel к девайсу \Device\AFD, которое отправляет TDI IRP-пакеты драйверам протокола, затем уже NDIS IRP-пакеты попадают в NDIS и через минипорт NDIS в драйвер сетевой карты, и потом в сеть. Если у тебя асинхронный сокет, то IRP пакет просто отмечается как отложенный (PENDING) и к тебе возвращается управление, а когда этот пакет "завершится" в kernel, он будет поставлен в очередь APC твоего потока и вот, когда твой поток получит управление (квант) он тебе и даст знать об OnReceive.


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Coocky
Дата 22.12.2005, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


GUI гуру
****


Профиль
Группа: Участник Клуба
Сообщений: 2879
Регистрация: 16.2.2004
Где: Украина. Запорожь е

Репутация: 25
Всего: 62



Dreamer_0x01
что-то запарился ты с сокетами.
Давай сюда проблему твою, сейчас решим smile


--------------------
Верю в смерть после жизни, в любовь после секса ,в крем после бритья smile        
PM ICQ   Вверх
Dreamer_0x01
Дата 22.12.2005, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Да собственно что нужно.

Нужно, чтобы в программе были функции, работающие одинаково и с сокетами, и с ком-портом.

То есть где-то у меня есть струтура, в которой хранится инфа о том, с каким устройством какое соединение установлено, и эти вункции в зависимости от полей этой структуры рабтают либо с те, либо с другим.
И надо-то всего лишь адаптировать функции, использующие ReadFile(...) для работы с сокетами. То есть чтобы работа велась по тому же принципу:

1.В моем потоке команда типа Write отправляет информацию в сокет (это просто).
2.Мой прибор, работающий в режиме сервера, отвечает на этот запрос.(это сделано на отдельном контроллере).
3.В моем потоке команда типа Read ждет этого ответа прибора в течении какого-то времени. (У меня для этого используется таймаут ком-портов.)

Все это работает в своем, специально выделенном для этого потоке.

То есть мне самое сложное - грамотно дождаться ответа сокета в команде Read, так же, как это делается и для ком-порта. Пока что получается, но я бы сказал мягко говоря безграмотно - я наплодил кучу пользовательских сообщений, и вынес сокеты в отдельный поток, работает, но чувствую, что я с каждым днем перестаю понимать свой код =)


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Coocky
Дата 22.12.2005, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


GUI гуру
****


Профиль
Группа: Участник Клуба
Сообщений: 2879
Регистрация: 16.2.2004
Где: Украина. Запорожь е

Репутация: 25
Всего: 62



Цитата(Dreamer_0x01 @ 22.12.2005, 15:05)
Нужно, чтобы в программе были функции, работающие одинаково и с сокетами, и с ком-портом.

Парралельно?
Какие проблемы!
просто в функции OnRecieve() управляй потоком для ком-портов smile
Или я не правильно понял?
Ты не прогу распиши, а проблему. Именно конкретно проблему!



--------------------
Верю в смерть после жизни, в любовь после секса ,в крем после бритья smile        
PM ICQ   Вверх
Dreamer_0x01
Дата 22.12.2005, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



поблема в том, что мне нужно сделать именно ОЖИДАНИЕ.
Рассмотрим на примере коннекта (его я тоже сделал по ожиданию)

Вот класс, производного от CAsyncSocket:

Код

#define CLIENTSOCK_DISCONNECT 0
#define CLIENTSOCK_CONNECT 1

class MyClientSocket : public CAsyncSocket
{
private:
    CRITICAL_SECTION cs; //для внтренних нужд
    BOOL Ready;    //флаг готовности приема данных
    
    unsigned char SockState;    //см.дефайны выше
    HANDLE MyTimer;    //для внутренних нужд
public:
    MyClientSocket();
    virtual ~MyClientSocket();
    virtual void OnClose(int nErrorCode);
    virtual void OnConnect(int nErrorCode);
    virtual void OnReceive(int nErrorCode);
    UINT Read(void * buf, UINT nToRead, UINT TimeOut, int *ErrorCode);//дождаться получения данных
    UINT Write(void * buf, UINT nToWrite, int * ErrorCode);//отправить запрос и выставить флаги
    unsigned char GetState(void);//узнать состояние сокета
    BOOL MakeConnect(LPCTSTR hostN , UINT portN,UINT TimeOut=1000);//дождаться коннекта
    void Disconnect(void);
};


Вот что порисходит по вызову функции OnConnect.
Код

void MyClientSocket::OnConnect(int nErrorCode)
{
    if(!nErrorCode)
    {
        ::EnterCriticalSection(&cs);
        SockState=CLIENTSOCK_CONNECT;//коннект установлен
        ::LeaveCriticalSection(&cs);
    }
    CAsyncSocket::OnConnect(nErrorCode);
}


А вот собственно функия, которую я хочу вызывать вне класса (по аналогичному принципу я собираюсь вызывать и функцию Read, использующую флаг Ready, выставляемый в функции OnReceive, но этопотом..)

Код

BOOL MyClientSocket::MakeConnect(LPCTSTR hostN , UINT portN,UINT TimeOut)
{
    BOOL result=TRUE;
    if(this->SockState==CLIENTSOCK_CONNECT)return TRUE;
    Create();
    if(this->Connect(hostN,portN))
    {
    }
    else
    {
        int errcode=GetLastError();
        if(errcode!=WSAEWOULDBLOCK)
        {
            result=FALSE;
            Close();
        }
    }
    if(!result)return FALSE;
    LARGE_INTEGER lDT;
    lDT.QuadPart=0;
    ::SetWaitableTimer(MyTimer,&lDT,1,NULL,NULL,NULL);
    unsigned char state;
    do//вот здесь крутимся, пока не поймаем коннект
    {
        ::EnterCriticalSection(&cs);
        state=this->SockState;
        ::LeaveCriticalSection(&cs);
        TimeOut--;
        ::WaitForSingleObject(MyTimer,100);
    }while((TimeOut)&&(state==CLIENTSOCK_DISCONNECT));
    ::CancelWaitableTimer(MyTimer);
    ::EnterCriticalSection(&cs);
    if(SockState==CLIENTSOCK_CONNECT)result=TRUE;
    else result=FALSE;
    ::LeaveCriticalSection(&cs);
    return result;
}

void MyClientSocket::Disconnect(void)
{
    ::EnterCriticalSection(&cs);
    Close();
    SockState==CLIENTSOCK_DISCONNECT;
    ::LeaveCriticalSection(&cs);
}


Я в функции OnConnect поставил бреакпоинт.
И при запуске фуекции MakeConnect(...) просто проходит цикл опроса, пока не исчерпается таймаут, и все...На брекпоинт мы не попадаем, хотя соединение должно установиться. (Во всяком случае серверная часть написанная по-простому, OnAccept выдает).
Вот я и не понимаю, кто должен вызвать функцию OnConnect ?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Coocky
Дата 22.12.2005, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


GUI гуру
****


Профиль
Группа: Участник Клуба
Сообщений: 2879
Регистрация: 16.2.2004
Где: Украина. Запорожь е

Репутация: 25
Всего: 62



Ты конектишься и хочешь работать только в том случае, если коннект удачный?
Но ответ от функции коннет занимает некоторое время, которое ты должен подождать, что б узнать результат соединения?
Я правильно понял?
Добавлено @ 19:15

Цитата(Dreamer_0x01 @ 22.12.2005, 16:12)
в функции OnConnect поставил бреакпоинт.
И при запуске фуекции MakeConnect(...) просто проходит цикл опроса, пока не исчерпается таймаут, и все...На брекпоинт мы не попадаем, хотя соединение должно установиться. (Во всяком случае серверная часть написанная по-простому, OnAccept выдает).
Вот я и не понимаю, кто должен вызвать функцию OnConnect ?

Покажи мне код, где ты создаешь гнездо,и прослушиваешь запрос на соединение?
Ты делаешь Listen() ?

Цитата(Dreamer_0x01 @ 22.12.2005, 16:12)
Вот я и не понимаю, кто должен вызвать функцию OnConnect ?


Все виртуальные функции OnConnect(),OnAccept(),OnRecieve() должны быть перегружены в твоем классе,производном от CAsyncSocket, что у тебя и иметтся.
Они вызываются когда СИСТЕМА генерирует события о прослушивании,приеме, закрытии и т.д.
Как это происходит внутри МФС, и незнаю, да и ненадо это знать



--------------------
Верю в смерть после жизни, в любовь после секса ,в крем после бритья smile        
PM ICQ   Вверх
Coocky
Дата 22.12.2005, 19:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


GUI гуру
****


Профиль
Группа: Участник Клуба
Сообщений: 2879
Регистрация: 16.2.2004
Где: Украина. Запорожь е

Репутация: 25
Всего: 62



И вообще, покажи ,как ты создаешь гнезда в клинтской и серверной части.
Надеюсь у тебя их две smile


--------------------
Верю в смерть после жизни, в любовь после секса ,в крем после бритья smile        
PM ICQ   Вверх
Dreamer_0x01
Дата 22.12.2005, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Цитата(Coocky @ 22.12.2005, 19:08)
Ты конектишься и хочешь работать только в том случае, если коннект удачный?
Но ответ от функции коннет занимает некоторое время, которое ты должен подождать, что б узнать результат соединения?
Я правильно понял?


Именно. И то же самое для приема данных - нужно обязательно дождаться.



Цитата(Coocky @ 22.12.2005, 19:08)
Покажи мне код, где ты создаешь гнездо,и прослушиваешь запрос на соединение?
Ты делаешь Listen() ?


В смысле, Listen в серверной части? Обязательно! Но здась у меня именно клиентская, и я делаю именно Connetc. Она работоспособная, за это ручаюсь, так как в старой версией, где все сокеты были засунуты в оконные классы и им слались сообщения, все соединялось, передавалось как надо.
И серверную часть я сейчас не трогаю, она в отдельном приложении.

Но если такие уж сомнения, вот серверная часть, но она работает, проверялось не раз:

Код

#define MY_SOCK_MSG WM_USER+1

#define MY_SOCK_ACCEPT 1
#define MY_SOCK_CLOSE 2
#define MY_SOCK_CONNECT 3
#define MY_SOCK_RECEIVE 4
#define MY_SOCK_SEND 5


// MyCock command target

class MyCock : public CAsyncSocket
{
public:
    MyCock(CWnd *);
    virtual ~MyCock();
private:
    CWnd * parent;
public:
    virtual void OnAccept(int nErrorCode);
    virtual void OnClose(int nErrorCode);
    virtual void OnConnect(int nErrorCode);
    virtual void OnReceive(int nErrorCode);
    virtual void OnSend(int nErrorCode);
};



Код



MyCock::MyCock(CWnd * wnd)
{
    this->parent=wnd;
}

void MyCock::OnAccept(int nErrorCode)
{
    // TODO: Add your specialized code here and/or call the base class
    parent->SendMessage(MY_SOCK_MSG,MY_SOCK_ACCEPT,nErrorCode);


//    CAsyncSocket::OnAccept(nErrorCode);
}

void MyCock::OnClose(int nErrorCode)
{
    // TODO: Add your specialized code here and/or call the base class
    parent->SendMessage(MY_SOCK_MSG,MY_SOCK_CLOSE,nErrorCode);

//    CAsyncSocket::OnClose(nErrorCode);
}

void MyCock::OnReceive(int nErrorCode)
{
    // TODO: Add your specialized code here and/or call the base class
    parent->SendMessage(MY_SOCK_MSG,MY_SOCK_RECEIVE,nErrorCode);


//    CAsyncSocket::OnReceive(nErrorCode);
}

void MyCock::OnSend(int nErrorCode)
{
    // TODO: Add your specialized code here and/or call the base class
    parent->SendMessage(MY_SOCK_MSG,MY_SOCK_SEND,nErrorCode);


//    CAsyncSocket::OnSend(nErrorCode);
}

void MyCock::OnConnect(int nErrorCode)
{
    // TODO: Add your specialized code here and/or call the base class
    parent->SendMessage(MY_SOCK_MSG,MY_SOCK_CONNECT,nErrorCode);

//    CAsyncSocket::OnConnect(nErrorCode);
}



Вот создание прослушки:

Код

//(в классе:    MyCock *sock;MyCock temp_sock;)

    this->sock=new MyCock(this);
    this->portN=4000;//объявлено ранее как UINT

    this->sock->Create(this->portN);
    this->sock->Listen();



И собственно вот:
Код

LRESULT CEtNetDlg::OnServSockMsg(UINT w,LONG l)
{
    switch(w)
    {
        case MY_SOCK_CLOSE:
            temp_sock.Close();
//далее мои действия, касающегося всего остального...
        break;
        case MY_SOCK_ACCEPT:
            if(this->sock->Accept(this->temp_sock))
            {
            }
            else
            {
                MessageBox("Serv:OnAccept ERROR!");
            }
//мои действия, касающегося всего остального...
        break;
        case MY_SOCK_RECEIVE:
            char* pBuf = new char[1025];
            int iBufSize = 1024;
            int iRcvd;
            CString strRecvd;
            iRcvd = this->temp_sock.Receive(pBuf, iBufSize);
            if (iRcvd == SOCKET_ERROR)
            {
                MessageBox("╬°шсър яЁшхьр");
            } else
            {
//мои действия, касающегося всего остального...
            }
        break;
    }
//мои действия, касающегося всего остального...
    return 0;
}



Так что с серверной частью порядок, прослушку она делает, Ассепт по коннекту тоже...

Вот в клиентской части, как видишь, возникли проблемы с ожиданием...


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 22.12.2005, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



А с обработкой сообщений всё Ок? WM_SOCKET_NOTIFY идут? Для теста удобно использовать сканер, например, XSpider - можно проверить (на localhost) клиента и сервер.


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 22.12.2005, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Цитата(JoyEx @ 22.12.2005, 20:52)
WM_SOCKET_NOTIFY идут?

Это что такое?



--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
Coocky
Дата 23.12.2005, 12:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


GUI гуру
****


Профиль
Группа: Участник Клуба
Сообщений: 2879
Регистрация: 16.2.2004
Где: Украина. Запорожь е

Репутация: 25
Всего: 62



Цитата(Dreamer_0x01 @ 22.12.2005, 19:45)
Вот в клиентской части, как видишь, возникли проблемы с ожиданием...

Блин, так какую проблему рещать-проблему с синхронизацией ожидания и приема или проблему с неполучением сообщений?


--------------------
Верю в смерть после жизни, в любовь после секса ,в крем после бритья smile        
PM ICQ   Вверх
Dreamer_0x01
Дата 23.12.2005, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Желательно, обе. Так как решив торую, первая тоже решится сама собой.
Ну либо принципиально другое красивое решение первой проблемы...
Добавлено @ 15:54
Хорошо, я переформирую заново вопрос таким образом.

Мне нужно иметь три функции:

1. Функция "Соединиться" - она должна послать запрос на соединение и дождаться результата.
2. Функция "Послать буфер данных".
3. Функция "Принять буфер данных" - должна иметь какой-то таймаут, в течение которого должна дождаться получения нужного количества байт из сокета.

Как, сколько классов надо будет завернуть в это дело, сколько потоков наплодить - в общем-то без разницы, главное, чтобы работало.


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 23.12.2005, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата(Dreamer_0x01 @ 22.12.2005, 21:17)
Цитата (JoyEx @ 22.12.2005, 20:52)
WM_SOCKET_NOTIFY идут?


Это что такое?


Смотри реализацию CAsyncSocket в sockcore.cpp
OnReceive и т.п. OnXXX вызываются из обработчика WM_SOCKET_NOTIFY CSocketWnd::OnSocketNotify()



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 23.12.2005, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



да, но при чем тут СSocketWnd ?
Ведь CAsyncSocket унаследован от CObject...., а CSocketWnd лишь объявлен для него как "друг"...

(смотрю файл afxsock.h)


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 23.12.2005, 18:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата(Dreamer_0x01 @ 23.12.2005, 18:09)
да, но при чем тут СSocketWnd ?


Смотри CAsyncSocket::AttachHandle() и выше. Видать $M решили извещения посылать через обычную очередь сообщений (для этого и СSocketWnd), если будешь ее "тормозить", то тогда и не дождёшься OnReceive и т.п..


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 23.12.2005, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



блин, так что, в каждом сокете еще и оконный класс получается создается?
Во изващение...


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 23.12.2005, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата(Dreamer_0x01 @ 23.12.2005, 19:02)
блин, так что, в каждом сокете еще и оконный класс получается создается?
Во изващение...

Окно ведь invisible! Мне оно не мешает.
А как Windows XP переводится? Окошки XP?! Да? smile

Чтобы поток был GUI он должен иметь окно (точнее очередь сообщений и т.п.), первичный поток всегда GUI-поток. Ну вот, MFC сделали по принципу "всё гениальное просто" и не стали придумывать колесо - сделали извещения через СSocketWnd


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 23.12.2005, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Да, но оконный класс я так понял, хоть и имеет свою очредь сообщений, но эта очередь сообщений должна "прокручиваться" каким-то интерфейсным потоком. Который я так понимаю является тем потоком, в котором я создаю сокет и объявляю AfxSocketInit, так?
Тогда мне наверное следует создать свой интерфейсный поток именно для этих целей, чтобы в ожидании не "усыплять" поток, который должен будет "прокручива" эту очередь сообщений.
Правильно?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 23.12.2005, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Сишный оконный класс всего лишь обслуживает настоящее Windows окно (subклассит), очередь сообщений есть у GUI-потока, она "прокручивается" всегда примерно вот так:
Код

    while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
    { 
        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    } 


Там, где есть окно там и есть GUI поток.

Цитата(Dreamer_0x01 @ 23.12.2005, 19:32)
Тогда мне наверное следует создать свой интерфейсный поток именно для этих целей, чтобы в ожидании не "усыплять" поток, который должен будет "прокручива" эту очередь сообщений.
Правильно?

ну да, чтобы не было deadlock (взаимоблокировки).



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 23.12.2005, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Вот, наконец-то я тогда начинаю понимать, почему не вызываются события сокета - потому что собственно некому их вызывать...

Ладно, щас попробуем все еще и в потоковые классы завернуть.
Была у меня конечно идея использовать синхронный сокет (который CSocket), но там заче-то надо порождать классы CArchive, СSocketFile, по-моему, слишком тяжеловесно. Думаю, получится написать свой синхронный сокет, благо мне не та много от него надо.


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 23.12.2005, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Dreamer_0x01
Зачем переделывать код? Надо всего лишь "прокачать" очередь сообщений, чтобы сообщения были обработаны родной оконой процедурой какого-то окна, а потом продолжать чё-то свое делать.


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 23.12.2005, 20:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Цитата(JoyEx @ 23.12.2005, 19:58)
Надо всего лишь "прокачать" очередь сообщений, чтобы сообщения были обработаны родной оконой процедурой какого-то окна, а потом продолжать чё-то свое делать.


Это как? Притащить в оно цепочку указателей на мой сокет, и там принудительно сделать его DispatchMessage ?



--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 23.12.2005, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Нет.
С помощью PeekMessage()-TranslateMessage()-DispatchMessage() можно "прокачать" очередь в любом месте потока.
Добавлено @ 20:26
Код

    MSG msg;

    while(::PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)){
        if(msg.message == WM_QUIT) break;
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 23.12.2005, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Не понимаю, в какое именно место мне надо такой код добавить?


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 23.12.2005, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата(Dreamer_0x01 @ 23.12.2005, 20:41)
Не понимаю, в какое именно место мне надо такой код добавить?


там, где у тебя долго выполняется код


smile I'll be back (from The Terminator)
Пока!

Это сообщение отредактировал(а) JoyEx - 23.12.2005, 20:44


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 23.12.2005, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



ВАХ! ну наконец-то заработало!
Единственное...поясни пожалуйста, почем в PeekMessage в качестве дескриптера окна передается NULL.
smile


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 24.12.2005, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата(Dreamer_0x01 @ 23.12.2005, 20:57)
Единственное...поясни пожалуйста, почем в PeekMessage в качестве дескриптера окна передается NULL


Чтобы вытаскивать из очереди сообщения всех окон данного потока, вот что пишут $M:
Цитата(MSDN)

If hWnd is NULL, PeekMessage retrieves messages for any window that belongs to the current thread.


PeekMessage() в отличие от GetMessage() "прокачивает" очередь, т.е. если в очереди нету сообщений PeekMessage() возвращает управление (=0), а GetMessage() только при получении WM_QUIT.

Вот тебе мой макет
Код

class ASocket: public CAsyncSocket{

    void OnConnect(int nErrorCode ){

        if(nErrorCode != 0) return;

        char buff[] = "Hello!!!";
        int len = strlen(buff)+1;
        Send (buff, len);
    }
};


Это ф-ция потока:
Код

UINT MyControllingFunction( LPVOID pParam ){

    ASocket asocket;

    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD(2, 2);

    WSAStartup( wVersionRequested, &wsaData );

    asocket.Create ();
    asocket.Connect ("127.0.0.1", 80);

    MSG msg;
    while(GetMessage (&msg, 0, 0, 0) == TRUE){

        if(msg.message == 0x00000373 /*WM_SOCKET_NOTIFY*/){
            TRACE("\nOkay!!!\n");
        }
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }

    return 0;
}



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 25.12.2005, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Что ж, ты мне этой штукой (конструкцией с PeekMessage)очень помог, причем как выяснилось, не тоьлко в сокетах, а вообще в большинстве мест, где моя программа "подтормаживала".

Спасибо.

Репутация "+".


--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 25.12.2005, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Dreamer_0x01, спасибо.

Для справки: В MS VС++ из Class View v7 очень удобно и быстро можно попасть на базовый класс (и его .cpp) через "Bases and Interfaces".



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0968 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.