На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
  
> Чайниковский вопрос про CSocket и thread
    Заранее сорри за чайниковский вопрос.
    Вот назрела проблема. В проге открываю сокет на прослушку. При коннекте к нему создаю новый сокет, и акцепчу к текущему. Хотелось бы, чтобы вся дальнейшая работа с этим новым сокетом происходила в своем треде.
    Так вот вопрос. Как правильно сделать - в главном потоке создать сокет для работы с соединением, сделать accept, а потом передать этот сокет как параметр в ф-ию потока, или создать ф-цию потока, а в ней уже создавать новый сокет.
    И второй вопрос - а как заставить правильно ф-цию потока выполняться до завершения коннекта с сокетом.
    Извините за сумбур. Пишу в виндах совсем недавно.
    Заранее спасибо.
      Именно в главном потоке создается слушающий сокет, по accept создается поток, в потоке создается сокет, которому нередается SOCKET handle.
      Примерно так:
      void CListenSocket::OnAccept(int nErrorCode)
      {
      CSocket soc;
      Accept(soc);
      CConnectThread* pThread = (CConnectThread*)AfxBeginThread(RUNTIME_CLASS(CConnectThread),
      THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
      ASSERT(pThread);
      pThread->m_hSocket = soc.Detach();
      pThread->ResumeThread();
      CAsyncSocket::OnAccept(nErrorCode);
      }
      А чтобы поток закрывался после закрытия сокета, в обработчике OnClose сокета надо
      отправить WM_QUIT потоку.
        Надеюсь ты не юзаешь MFC-классы для работы с сокетами? Если хочешь многопоточности, то обходи MFC стороной.
        >Так вот вопрос. Как правильно сделать - в
        >главном потоке создать сокет для работы с
        >соединением, сделать accept, а потом
        >передать этот сокет как параметр в ф-ию
        >потока, или создать ф-цию потока, а в ней
        >уже создавать новый сокет.
        1. IMHO не принципиально. Но по моему лучше передать уже готовый сокет. Ведь поток может стартовать не так уж и сразу. Твоя ф-ция обработки сокетовых сообщений к тому времени может завершиться и получить новое сообщение...
        2. Всё просто. Устанавливаешь евент на событие от сокета и зацикливаешь поток пока не получишь FD_CLOSE. Почитай http://www.sources.ru/cpp/cpp_network_evets_winsock2.shtml
        Вот кусок исхода из моей проги:
        DWORD WINAPI CCafe::SockThread(LPVOID ts)
        {
        //........ Тут ещё всякий код
        //Устанавливаем событие на сообщения сокета
        HANDLE hEvent = WSACreateEvent();
        if(::WSAEventSelect(MyClass->sock, hEvent, FD_CONNECT|FD_READ|FD_CLOSE))
        {
        MessageBox(NULL,"SocketEventError","Socket error",MB_OK);
        return 2;
        }
        for(;;) //Вечный цикл :)
        {
        //Вдруг нужно закрыть все потоки потому
        // что главный поток завершается. Нужно
        // корректно завершить работу.
        if(WaitForSingleObject(CloseEvent,0 )==WAIT_OBJECT_0)
        {
        shutdown(MyClass->sock,2);
        closesocket(MyClass->sock);
        WSACloseEvent(hEvent);
        return 0;
        }

        //А теперь собственно ждём события от сокета
        if( WSA_WAIT_FAILED!=::WSAWaitForMultipleEvents(1, &hEvent, false,50,false))
        {
        WSANETWORKEVENTS NetEv;
        if(0==WSAEnumNetworkEvents(MyClass->sock,hEvent,&NetEv))
        {
        // Если что-то пришло
        if(NetEv.lNetworkEvents & FD_READ)
        {
        //Читаем из сокета
        recv(sock,(char*)buf,sizeof(buf),NULL);
        //....... Ну и т.д.
        }
        else
        if(NetEv.lNetworkEvents & FD_CLOSE)
        { //Если хост разорвал соединение
        WSACloseEvent(hEvent); //Освобождаем ресурсы
        return 0; //Завершаем поток
        }
        } //if(0==WSAEnumNetworkEvents
        } //if( WSA_WAIT_FAILED!
        } //for(;;)
        }//SockThread()

        Ну вот, примерно так.
          Ну я читал про "многопоточность" MFC, а что, все так запущено?
            Незнаю насколько там всё запущено, но я несколько раз тыкался носом в exception казалось бы из неоткуда и больше не хочу. Может я просто не умею пользоваться MFC-многопоточностью....
              Ну, не знаю. Сколько многопоточных приложений MFC писал - все нормально работает.
                2necer : Может подкинешь пару ссылок где про это можно почитать?
                  Ну, я только MSDN'ом и пользуюсь.
                  Хотя... помнится где-то валялись у меня какие-то семплы, насколько помню, с microsoft.com стянутые. Если найду, куда кинуть-то? Вообще, там все довольно просто (на то и MFC), единственно, неколько геморройно иногда организовывать синхронизацию потоков, но это и в API не лучше. :)
                    2 necer
                    Если найдешь, то и мне.
                    На мыло...
                    Спасибо.
                      2necer: на server_mouse@chat.ru ;)
                        Что не так?
                        Делаю:
                        class CServerThread : public CWinThread {
                        public:
                        CClientSocket soc //класс для работы с сокетом
                        ////
                        }
                        В главном потоке определяю класс CMySocket
                        CMySocket::OnAccept(int nErrorCode)
                        {
                        CSocket soc;
                        Accept(soc);
                        CSocketThread* pThread = (CSocketThread*) AfxBeginThread(RUNTIME_CLASS(CSocketThread),
                        THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
                        ASSERT(pThread);
                        pThread->soc.Attach(soc.Detach());
                        pThread->ResumeThread();
                        CSocket::OnAccept(nErrorCode);
                        }
                        class CClientSocket : public CSocket
                        {
                        public:
                        CServerThread *m_ServThread; //указатель на поток, в котором "живет" данный сокет
                        устанавливается в
                        CServerThread::InitInstance
                        ///////////
                        }
                        CServerThread::InitInstance
                        {
                        soc.m_ServThread = this;
                        /////
                        }
                        Определяю обработчик:
                        CClientSocket::OnClose(int nErrorCode)
                        {
                        CSocket::OnClose(nErrorCode);
                        m_ServThread->PostThreadMessage(WM_QUIT,0,0);
                        }
                        И после отключения клиента от порта закрывается прога.
                        Что я делаю не так?
                          Ну, на первый взгляд все верно. Попробуй отследить, куда попадает сообщение WM_QUIT.
                          Может, ты его в главный поток нечаянно отправляешь?
                          P.S. Пример выслал alexv и server_mouse
                            ех если возможно то вышли и мне на мыло (((divlweb@mail.ru))) MFC-многопоточностью...
                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                            0 пользователей:


                            Рейтинг@Mail.ru
                            [ Script execution time: 0,0287 ]   [ 16 queries used ]   [ Generated: 17.06.24, 10:08 GMT ]