15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


CSocket and threads

John Addis -- jaddis@erols.com
Saturday, March 30, 1996

Environment:
  NT 3.51,  VC++ 4.0, _AFXDLL,  sockcore.cpp line 709
  '95,      VC++ 4.1, _AFXDLL,  sockcore.cpp line 694

Here's the scenario; typical client/server development. When a client 
connects I want to create a new thread (and a socket to go along with 
it) to service the client. 

The accept() call works okay and MFC creates a *new* CSocketWnd to go 
along with my CSocket object. The _AFX_SOCK_THREAD_STATE for the new 
thread *is*  different from that of the main thread. The m_hSocketWindow 
members are also different.

However... when notifications come in for the socket in the _child 
thread_ they go to the CSocketWnd for the socket in the _main thread_. 
(I discovered this by tracing through in the debugger.) When 
CAsyncSocket::DoCallBack() uses LookupHandle() to map the hSocket 
(wParam) to a CSocket* it fails -- it is looking in the map for the 
wrong thread.

Anybody have any ideas on how to fix this? Is it simply not possible to 
use CSocket in this manner? 

Abbreviated code follows:
------------------------
void CTestSock::OnAccept(int n)
{
  CSocket::OnAccept(n);
  ::AfxBeginThread( ::ThreadProc, this );
}
UINT ThreadProc(LPVOID pParm)
{
  CSocket* pListener = (CSocket*)pParm;
  CServerSock sock;
  pListener->Accept( sock );

  BOOL bMore = TRUE;
  while( bMore )
  {
    if (::WaitMessage())
    {
      // process the message
    }
  }
  return 0;
}

tia (even if your answer sucks, Mike)

-- 
John Addis        Master of Time and Space
jaddis@erols.com  C++, MFC, Win32, Win95, TCP/IP
"Invalid or missing REALITY.COM Universe halted."




Dean McCrory -- deanm@microsoft.com
Sunday, March 31, 1996

You can't pass CSocket* between threads like that (as you have
discovered...).

Instead of passing the CSocket*, you should instead pass the handle to
the socket to the other thread.

>void CTestSock::OnAccept(int n)
>{
>  CSocket::OnAccept(n);
>  ::AfxBeginThread( ::ThreadProc, m_hSocket );
>}
>UINT ThreadProc(LPVOID pParm)
>{
        CAsyncSocket listener;
        listener.Attach((SOCKET)pParam);
        CServerSock sock;
        listener.Accept(sock);
        listener.Detach();
        ....

// Dean McCrory
// Team Jakarta

>----------
>From: 	John Addis[SMTP:jaddis@erols.com]
>Sent: 	Friday, March 29, 1996 10:04 PM
>To: 	mfc-l@netcom.com
>Subject: 	CSocket and threads
>
>Environment:
>  NT 3.51,  VC++ 4.0, _AFXDLL,  sockcore.cpp line 709
>  '95,      VC++ 4.1, _AFXDLL,  sockcore.cpp line 694
>
>Here's the scenario; typical client/server development. When a client 
>connects I want to create a new thread (and a socket to go along with 
>it) to service the client. 
>
>The accept() call works okay and MFC creates a *new* CSocketWnd to go 
>along with my CSocket object. The _AFX_SOCK_THREAD_STATE for the new 
>thread *is*  different from that of the main thread. The
>m_hSocketWindow 
>members are also different.
>
>However... when notifications come in for the socket in the _child 
>thread_ they go to the CSocketWnd for the socket in the _main thread_. 
>(I discovered this by tracing through in the debugger.) When 
>CAsyncSocket::DoCallBack() uses LookupHandle() to map the hSocket 
>(wParam) to a CSocket* it fails -- it is looking in the map for the 
>wrong thread.
>
>Anybody have any ideas on how to fix this? Is it simply not possible to
>
>use CSocket in this manner? 
>
>Abbreviated code follows:
>------------------------
>void CTestSock::OnAccept(int n)
>{
>  CSocket::OnAccept(n);
>  ::AfxBeginThread( ::ThreadProc, this );
>}
>UINT ThreadProc(LPVOID pParm)
>{
>  CSocket* pListener = (CSocket*)pParm;
>  CServerSock sock;
>  pListener->Accept( sock );
>
>  BOOL bMore = TRUE;
>  while( bMore )
>  {
>    if (::WaitMessage())
>    {
>      // process the message
>    }
>  }
>  return 0;
>}
>
>tia (even if your answer sucks, Mike)
>
>-- 
>John Addis        Master of Time and Space
>jaddis@erols.com  C++, MFC, Win32, Win95, TCP/IP
>"Invalid or missing REALITY.COM Universe halted."
>
>



Les -- Les.Hill@FMR.Com
Monday, April 01, 1996

[Mini-digest: 2 responses]

To use CAsyncSocket here is what I have done in the past (I image
CSocket would be similar):

use ::accept() to get a raw SOCKET create your new thread passing the
raw socket use Attach to make the connection from the raw Socket to
CAsyncSocket (this will create the CSocketWnd as well)

Another key point: because a socket inherits its parents async select
settings, the parent should only be getting accept notifications (you
then set the child's settings in the select call -- this is probably
all you need to do to get your code working).

Les Hill
leh@cybercom.net

-----From: odecio@ISF.COM

     I'll give it a try. The problem is that you are sending the *this* 
     pointer to the working thread, and accept()-ing the socket referencing 
     it. That is probably the reason why you receive the notifications in 
     the _main_ thread. 
     
     As I remember, a working thread does not deal with Windows messages. 
     (and the socket notifications are such). Maybe you should use 
     CWinThread as a basis for a new class that contains a CSocket, and 
     your main thread keeps a list of them.
     
     Hope this helps.
     
     Otavio





| Вернуться в корень Архива |