Скачать MetaTrader 5

Друзья, помогите с CSocket::OnReceive

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
o_o
Модератор
23919
o_o  
Использую мфцешный класс CSocket.


В обычном диалоговом приложении все отрабатывает четко. Отправка по Send, прием по событию на OnReceive без проблем.

Но при переносе класса в dll - функция OnReceive не вызывается.
то есть начало отрабатывает нормально (Create/Connect), и функция отправки Send работает. Но функция OnReceive, для инициализации приема не вызывается.

В гугле уже обчитался, эта проблема частая, но предлагаемого решения не нашел.
Моя догадка, что вызов события до сокета почему то не передается. Причина может быть, что поток этой dll, в котором сокет создается, не отправляет его окну (CSocketWnd) требуемое событие, ну и как следствие OnReceive не вызывается.

Может надо окно создать и в нем сокет.
Или UI-поток ? С потоком кстати я пытался сделать (AfxBeginThread), но OnReceive тоже не заработал.

Помогите советом или кодом, кто чем может, а то затраха замучился с ним.

вот весь код что в DLL

class CExtSocket : public CSocket
{
public:
  CExtSocket(){};
  virtual ~CExtSocket(){};

  virtual void OnReceive(int nErrorCode);  <--- вот эта козявка меня добивает
};

void CExtSocket::OnReceive(int nErrorCode)
{
  AfxMessageBox(_T("Receive"));
  CSocket::OnReceive(nErrorCode);
}


#define EXT extern "C" __declspec(dllexport)

CExtSocket sock;

//------------------------------------------------------------------    _Create
EXT int __stdcall _Create() // создание объекта сокета
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  return(sock.Create());
}
//------------------------------------------------------------------    _Connect
EXT int __stdcall _Connect(LPCTSTR addr, UINT port) // подключение сокета к хосту
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  return(sock.Connect(addr, port));
}
//------------------------------------------------------------------    _Send
EXT int __stdcall _Send(void *buf, int len, int flag=0) // отправляем буфер в сокет длиной len
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  return(sock.Send(buf, len, flag));
}
//------------------------------------------------------------------    _Receive
EXT int __stdcall _Receive(void *buf, int len, int flag=0) // принимаем байтовый буфер длиной len
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  return(sock.Receive(buf, len, flag));
}
//------------------------------------------------------------------    _Close
EXT void __stdcall _Close() // закрываем сокет в системе
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  sock.Close();
}
Андрей
1890
Андрей  

Я бы попробовал стартовать под мфц отдельный поток,
чтобы он создавал все окошки и проводил инициализацию.

Т.е. все должно происходить именно "с нуля".

Создали поток- дальше он вызвал инициализацию мфц,
дальше мфц создало главное окно.

o_o
Модератор
23919
o_o  

Да, Андрей, так на некоторых сайтах и видел, предлагали.

Для этого создал поток от CWinThread. - по AfxBeginThread(CRuntimeClass* ....

Но вот дальше надо создать окно в нем ? А подскажи как и где? в InitInstance ?

вот что делал

// CSockThread
class CSockThread : public CWinThread
{
        DECLARE_DYNCREATE(CSockThread)
public:
        CExtSocket *sock; // <---- переносил сокет в поток

public:
  CSockThread();
  virtual ~CSockThread();

public:
  virtual BOOL InitInstance();
  virtual int ExitInstance();

protected:
  DECLARE_MESSAGE_MAP()
};

CSockThread *thread=NULL; // <---экзмпляр этого потока

//------------------------------------------------------------------    _InitThread
EXT int __stdcall _InitThread(int hwnd) // создание объекта сокета
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
 
  if (wnd==NULL) wnd=new CWnd; wnd->Attach((HWND)hwnd); // <--- это окно чарта
  //создаем поток для обработки диалога
  if (thread!=NULL)     delete thread;  // проверка на предыдущую инициализацию
  thread=(CSockThread*)AfxBeginThread(RUNTIME_CLASS(CSockThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
  thread->m_pMainWnd=wnd; // передали в поток хендлер окна
  thread->ResumeThread(); // запустили поток
  return(1);
}

но сам поток у меня отвечал только на первое PostThreadMessage. Дальше то ли умирал, то ли зависал. В dll сложно дебаг делать, сложнее чем mql :)

Ну и соответственно окно ему подсунул от чарта. Думаю что это не совсем верно.

Андрей
1890
Андрей  
Подсказать не могу. Мфц не юзаю. В WTL поток создаю CreateThread().

Ну и типа повторюсь: по-моему, надо найти все мфц-шные статики и инициализации-
и запускать их в этом потоке как-то.

Может быть двухступенчатую ракету сделать.
Одна длль создает поток- запускает вторую,
а уже потом в нее ломится из потока МТ.
o_o
Модератор
23919
o_o  
пробовал и CreateThread. результат тот же. Вроде рекомендации дельные, но как это сделать...
Андрей
1890
Андрей  
Одна длль поднимает поток.

В этом потоке грузится 2я длль.
Запускается инициализация (как в винмайне).
В итоге поток будет висеть на оконной процедуре.

Для начала - так. Если сокет запашет то бинго.
Комбинатор
16087
Комбинатор  

Тут старО, но думаю будет полезно. Там кстати пример прокси есть.

Правда совсем не MFC.

o_o
Модератор
23919
o_o  
jartmailru:

Запускается инициализация (как в винмайне).
как это сделать ? код покаж :)
а имеенно как оконную процедуру у потока сделать... в dll
Андрей
1890
Андрей  
так же как в винМайне.
а инициализация сама запустится при загрузке длла.
там ж статиков до хрена.

ха. код покаж.
я для втля этот код неделю писал.
для мфц не знаю возможно ли.

а сокеты у меня самописные кстати.
асинхронные но без подписки на окно.

хм. а ты чего моск паришь??
сокет в синхронном режиме на окно вроде и не вешается же.
o_o
Модератор
23919
o_o  
TheXpert:

Тут старО, но думаю будет полезно. Там кстати пример прокси есть.

Правда совсем не MFC.


да, не MFC...
o_o
Модератор
23919
o_o  
jartmailru:
так же как в винМайне.
а инициализация сама запустится при загрузке длла.

В принципе поток как таковой он может юыть привязан к окну. Но к сожалению в dll это надо самому прописывать, и наверно свое созданное окно в систему регистрировать. Затем поток как то к этому окну вязать и оконную процедуру. Вобщем я с этим никогда не сталкивался.

Но блин надо оооччень.


а сокеты у меня самописные кстати.
асинхронные но без подписки на окно.

то есть вы использовали исходные WSA функциии http://msdn.microsoft.com/en-us/library/ms741394%28v=VS.85%29.aspx ?
и затем бесконечный цикл на для recv() ?

сокет в синхронном режиме на окно вроде и не вешается же.

CSocket асинхронный.

12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий