WWW.ИСХОДНИКИ.РУ cpp.sources.ru
java.sources.ru web.sources.ru soft.sources.ru
jdbc.sources.ru asp.sources.ru api.sources.ru

  Форум на исходниках
  C / C++ / Visual C++
  Чайниковский вопрос про CSocket и thread

СПРОСИТЬ  ОТВЕТИТЬ
профайл | регистрация | faq

Автор Тема:   Чайниковский вопрос про CSocket и thread
alexv опубликован 02-10-2001 18:59 MSK   Click Here to See the Profile for alexv   Click Here to Email alexv  
Заранее сорри за чайниковский вопрос.
Вот назрела проблема. В проге открываю сокет на прослушку. При коннекте к нему создаю новый сокет, и акцепчу к текущему. Хотелось бы, чтобы вся дальнейшая работа с этим новым сокетом происходила в своем треде.
Так вот вопрос. Как правильно сделать - в главном потоке создать сокет для работы с соединением, сделать accept, а потом передать этот сокет как параметр в ф-ию потока, или создать ф-цию потока, а в ней уже создавать новый сокет.
И второй вопрос - а как заставить правильно ф-цию потока выполняться до завершения коннекта с сокетом.
Извините за сумбур. Пишу в виндах совсем недавно.
Заранее спасибо.
necer опубликован 03-10-2001 10:29 MSK     Click Here to See the Profile for necer  Click Here to Email necer     
Именно в главном потоке создается слушающий сокет, по 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 потоку.

server_mouse опубликован 03-10-2001 10:44 MSK     Click Here to See the Profile for server_mouse  Click Here to Email server_mouse     
Надеюсь ты не юзаешь 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()

Ну вот, примерно так.

alexv опубликован 03-10-2001 11:31 MSK     Click Here to See the Profile for alexv  Click Here to Email alexv     
Ну я читал про "многопоточность" MFC, а что, все так запущено?
server_mouse опубликован 03-10-2001 12:06 MSK     Click Here to See the Profile for server_mouse  Click Here to Email server_mouse     
Незнаю насколько там всё запущено, но я несколько раз тыкался носом в exception казалось бы из неоткуда и больше не хочу. Может я просто не умею пользоваться MFC-многопоточностью....
necer опубликован 03-10-2001 12:26 MSK     Click Here to See the Profile for necer  Click Here to Email necer     
Ну, не знаю. Сколько многопоточных приложений MFC писал - все нормально работает.
server_mouse опубликован 03-10-2001 12:32 MSK     Click Here to See the Profile for server_mouse  Click Here to Email server_mouse     
2necer : Может подкинешь пару ссылок где про это можно почитать?
necer опубликован 03-10-2001 12:47 MSK     Click Here to See the Profile for necer  Click Here to Email necer     
Ну, я только MSDN'ом и пользуюсь.
Хотя... помнится где-то валялись у меня какие-то семплы, насколько помню, с microsoft.com стянутые. Если найду, куда кинуть-то? Вообще, там все довольно просто (на то и MFC), единственно, неколько геморройно иногда организовывать синхронизацию потоков, но это и в API не лучше. :)
alexv опубликован 03-10-2001 12:53 MSK     Click Here to See the Profile for alexv  Click Here to Email alexv     
2 necer
Если найдешь, то и мне.
На мыло...
Спасибо.
server_mouse опубликован 03-10-2001 13:52 MSK     Click Here to See the Profile for server_mouse  Click Here to Email server_mouse     
2necer: на server_mouse@chat.ru ;)
alexv опубликован 03-10-2001 15:28 MSK     Click Here to See the Profile for alexv  Click Here to Email alexv     
Что не так?
Делаю:
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);
}

И после отключения клиента от порта закрывается прога.

Что я делаю не так?

necer опубликован 04-10-2001 13:19 MSK     Click Here to See the Profile for necer  Click Here to Email necer     
Ну, на первый взгляд все верно. Попробуй отследить, куда попадает сообщение WM_QUIT.
Может, ты его в главный поток нечаянно отправляешь?

P.S. Пример выслал alexv и server_mouse

divl опубликован 07-03-2001 12:12 MSK     Click Here to See the Profile for divl  Click Here to Email divl     
ех если возможно то вышли и мне на мыло (((divlweb@mail.ru))) MFC-многопоточностью...

СПРОСИТЬ  ОТВЕТИТЬ
Перейти:


E-mail | WWW.ИСХОДНИКИ.RU

Powered by: Ultimate Bulletin Board, Freeware Version 5.10a
Purchase our Licensed Version- which adds many more features!
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 2000.