Link to home
Start Free TrialLog in
Avatar of Raistlin589
Raistlin589

asked on

CSocket problem

I have a CWinThread that when run uses a CSocket object in Listen mode to wait for incoming calls.. after a specific time-out I wish to close
this thread and the socket.. but it keeps blocking, tried everything from
deleteing the socket (Assertion failure) to CancelBlockingCall and Close..
nothing works.. The problem is that the thread is used as a workerthread and has no window.. (this causes a exception on the Close() function..
The timeout of the CSocket object is also non-settable and so it keeps open forever.. The CSocket object is wrapped in a COM object.. but this gives no problems.. it can normally close, open, connect etc.. but when in listen mode
I can't exit the listen mode.. Really driving me nuts..

Am already thinking of changing everything to C++ Builder.. If I knew this would fix the problem..

The CSocket object is in a STREAM modus for synchronus transfer and this needs to be kept.. so please no answers stating to change to async modus.. (Tried that also, but listen keeps blocking and won't close or die..)

Thanks..
Jochen Rosenboom
Avatar of sunraj
sunraj

I am at the infant stage in socket programming. Please give me your mail id as i would like to know regarding socket programming.
But I have used multithreading in my project.
well...I do not know if the following would solve your problem. But let me share with you.

Are u specifying time out for the worker thread ?

The Assertion failure occurs inside the thread due to lot many reasons and one such thing is memmory leak. This is due to forceful termination of the thread and the memmory inside the thread is not properly deallocated.

If your problem is similar to one like above, then you have to synchronise your thread procedure.

Create an event object(in non signalled state) just before you create your thread.

when your time out period expires then set this event object to signalled state whose state is been monitored by the thread procedure. Then safetly close the socket handle.

regards!
Can you show us some code?
Hi !
There is no point to change everything to Borland C++, if you wish to have more conntrol over sockets you should use Raw win32 sockets API directly.
Avatar of Raistlin589

ASKER

Thanks, but I already use a windows message to close the thread, and the problem is not closing the thread or memory leaks (I have only one CString object in the complete application that leaks once 83 bytes..)
The problem is simply that the Socket blocks the complete thread from running (So the windows handler in the Run statement will never be reached..) and I wish to stop this socket from blocking.. after it stops blocking (or preferably is closed for reuse) I simply use a PostThreadMesssage(WM_QUIT,0,0) on the thread to let it kill itself.. works fine (tested this code many times..) the socket itself is the problem, since closing it when it's in listen mode
creates a assertion on pstate->m_SocketWIndow
inside the socket..

2 sun307
100% agree :)
So why do you use blocking mode?
Source of the thread (run part)

int C_ConnectorThread::Run()
{
      // If no user after 5 secs, destroy thread Yippie !@

      TRACE("C_ConnectorThread ONLINE\n");
      Ready.SetEvent();
      
      BOOL fDone = TRUE;
      MSG msg;

      while(fDone)
            {
            if((m_pNetworkOPL)&&(fDone))
                  {
                  BSTR TempString = _bstr_t(m_pIpAddress).copy();
                  m_pNetworkOPL->ConnectReceiveMode(&TempString,m_PortNr);
                  SysFreeString(TempString);
                  // contact user, give it the connected networkOPl back..
                  // nah.. just bleed it to death..
                  // without the release this one lives on inside the userthread
                  // long live da com commando's
                  
                  fDone = FALSE;
                  }
            while(PeekMessage(&msg, 0,  0, 0, PM_REMOVE))
                  if((msg.message == WM_QUIT)||(msg.message == WM_TIMER))
                        fDone = FALSE;
            Sleep(1000);
            }
      
      m_pOwner->RemoveConnectorThread(this);

      return 0;
}

source of the CSocket Com object (Connectreceive mode :

STDMETHODIMP C_NetworkOPL::ConnectReceiveMode(BSTR *apConnectionAddress, int aPortNr)
{
      AFX_MANAGE_STATE(AfxGetStaticModuleState())

      m_pConnectSocket = new CSocket();
      HRESULT hr = S_OK;
      BOOL Success = FALSE;
      m_PortNr = aPortNr;
      m_pConnectionAddress = new CString(*apConnectionAddress);
      
      if(m_pSocket)
            Success = m_pSocket->Create(m_PortNr,SOCK_STREAM);

      if(Success)
            {
            Success = m_pSocket->Listen(1);
            Success = m_pSocket->Accept(*m_pConnectSocket);
            }
      else
            hr = E_ABORT;
      
      if(!Success)
            {
            WriteError(1, &CString("ConnectReceiveMode"));
            hr = E_ABORT;
            }
      else
            {      
            WriteAction(&CString("ConnectReceiveMode"), &CString("Connect Receive Mode Success"));
            delete m_pSocketFile;
            m_pSocketFile = new CSocketFile(m_pConnectSocket);
            delete m_pArchive;
            m_pArchive = new CArchive(m_pSocketFile, CArchive::load);      
            m_SocketOpened = true;
            }

      return hr;
}

I'm not sure how to approach the API Sockets directly.. didn't find much help in MSDN about that topic.. if this could help fix the problem please show some source about it..

P.S. my mail address is jochen@satl.com

P.P.S. Close function of COM object only does
if(m_pSocket)
m_pSocket->Close()
I use blocking mode, because these sockets need to speak to JAVA sockets and those are synchronous stream sockets.. when using synchronous mode some socket functions block..
The windows sockets are based on windows sockets and are message based and it usually better for you to treat them in this manner than it would if you tried to use them as you would standard sockets (UNIX based ones)

A better way to have a listening socket would be to create a CListeningSocket :public CSocket and handle the Accept in the OnAccept handler

see the following MS KB articles

Q175668
Q193101
Q192570

and maybe Q214396

at http://msdn.microsoft.com
As stated the trouble is not the listen function, but making it stop while it's blocking...

handling the listen function with an accept is easy.. but am downloading the win32 sdk now..
will look into these things..

Thanks..
I don't think you are following me the way you have use the CSocket::Listen is wrong - you should handle all your accepts in the OnAccept handler see the examples for what I mean :)
The trouble is not a correct listen or accept, but the blocking of the socket that even refuses it's own close then because it's inside a thread..
To Accept via the OnAccept is a improvement on my code, but it won't cure the main problem and that is that while the socket does the Listen(1);
if a CLose on this socket is called it asserts because it can't find it's socketwindow..

I do not wish to accept that socket but close it due to a time-out..
Ah have you set AfxSocketInit in the InitInstance of your CWinThread object ?
ASKER CERTIFIED SOLUTION
Avatar of tchalkov
tchalkov

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks everybody.. I think this will help..

I'll Split up the point under you all..

Thanks a lot !

JR
Just search for your name to get the points..
(Your name is a question from me)

Comment to it and i'll accept it and award you with 100 pts..

thanks for the help..

JR