Поиск:

Ответ в темуСоздание новой темы Создание опроса
> CAsyncSocket и потоки, запутался, кто кого вызывает. 
:(
    Опции темы
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   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




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


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

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