Solved

CSocket problem

Posted on 2000-04-07
16
994 Views
Last Modified: 2013-11-20
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
0
Comment
Question by:Raistlin589
  • 7
  • 3
  • 3
  • +3
16 Comments
 

Expert Comment

by:sunraj
ID: 2693050
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!
0
 
LVL 6

Expert Comment

by:MichaelS
ID: 2693075
Can you show us some code?
0
 
LVL 2

Expert Comment

by:sun307
ID: 2693078
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.
0
 

Author Comment

by:Raistlin589
ID: 2693092
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..

0
 
LVL 6

Expert Comment

by:MichaelS
ID: 2693093
2 sun307
100% agree :)
0
 
LVL 6

Expert Comment

by:MichaelS
ID: 2693104
So why do you use blocking mode?
0
 

Author Comment

by:Raistlin589
ID: 2693125
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()
0
 

Author Comment

by:Raistlin589
ID: 2693130
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..
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2693324
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
0
 

Author Comment

by:Raistlin589
ID: 2693346
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..
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2693354
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 :)
0
 

Author Comment

by:Raistlin589
ID: 2693418
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..
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2693477
Ah have you set AfxSocketInit in the InitInstance of your CWinThread object ?
0
 
LVL 7

Accepted Solution

by:
tchalkov earned 500 total points
ID: 2693486
I made some experiments with CSocket and it seems that not Listen but Accept(..) is holidng the block. Have you confirmed that Listen is causing the block?
In the MFC Source Listen() simply calls the API function listen, while Accept is starting a loop.

So when you call Accept it starts a loop waiting for a incoming connection. In fact it calls a function PumpMessages, which is starting a loop which exits if there is a connection incoming or if a specified period of time has elapsed.

When PumpMessages loop is over it gets back to Accept function which again calls PumpMesssages
During PumpMesages loop if you call CancelBlockingCall() you can stop both loops.

The timeout for the inner loop is the member variable of the CSocket m_nTimeOut. It is public so you can access it even though it does not appear when you type in the Visual C++

If you call CancelBlockingCall from a different thread and this value is very small then it is not very likely that the other thread is in the PumpMessages Loop. And the flag which is used to interrupt blocking is initialized every time PumpMessages is Called.

There is no such problem if you call CancelBlockingCall from the same thread.

So a possible solution is to create your own class which inherits CSocket and to override the OnMessagePending function.

In that function check if the timeout has expired and if it has expired call CancelBlockingCall. This way you will call CancelBlockingCall in the same thread where you called Accept and it should work.

0
 

Author Comment

by:Raistlin589
ID: 2693542
Thanks everybody.. I think this will help..

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

Thanks a lot !

JR
0
 

Author Comment

by:Raistlin589
ID: 2693600
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
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Suggested Solutions

Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now