Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1071
  • Last Modified:

A CSocket question.

Colleagues,

Here is the problem. I have a class, which has a CSocket as a member vars:

// begin
class CDummyServerDlg : public CDialog
{
public:
     CSocket m_sendSock;
     CListeningSocket m_servSock;
     void ProcessPendingAccept(CListeningSocket* pSock);
//...
};
// end

Here is the OnAccept handler of the CListeningSocket:

// begin
void CListeningSocket::OnAccept(int nErrorCode)
{
     CSocket::OnAccept(nErrorCode);
     m_pDlg->ProcessPendingAccept(this);
}
// end

Here is the ProcessPendingAccept(), which causes ACCESS VIOLATION in the Accept() function:

// begin
void CDummyServerDlg::ProcessPendingAccept(CListeningSocket* pSock)
{
     CString strMessage;
     pSock->Accept(m_sendSock);
}
// end

It happens in the following place:

// begin
BOOL CAsyncSocket::Accept(CAsyncSocket& rConnectedSocket,
     SOCKADDR* lpSockAddr, int* lpSockAddrLen)
{
     ASSERT(rConnectedSocket.m_hSocket == INVALID_SOCKET);     // access violation here
     ...
}
// end

At the same time the following implementation of OnAccept (by example of MSDN CHATSRVR) doesn't cause the violation:

// begin
void CDummyServerDlg::ProcessPendingAccept(CListeningSocket* pSock)
{
     CString strMessage;
     CSocket* pSendSock = new CSocket;
     pSock->Accept(*pSendSock);
}
// end

I have checked: my code doesn't alter m_sendSock after it's constructed. Why does dynamically allocated work, and statically allocated causes access violation?

Thank you,
Kender
0
kender_a
Asked:
kender_a
  • 4
  • 2
  • 2
1 Solution
 
ackavaCommented:
hi kender,

CSocket and CAsyncSocket are dynamically implemented, you checkout what is IMPLEMENT_DYNAMIC etc, there are two techniques that MFC implements one is static and one is dynamic, this is done to make things thread safe and to allow one object to be used in different threads.

Internally windows might be accessing your object from its own thread but if you have made them static then they may not have access to your object since they might be on stack of on data segment, but if you create by new, it is located on heap which mfc's internal threads can access.

In such short times i can not explain you everything, may be even my words wont help you much to understand since it is not complete, your probably read IMPLEMENT_DYNAMIC macro and things related with it in msdn, you might get idea of it.

Using AsyncSocket is great problem, perhaps i would suggest you to use blocking socket but this is just beginning, you will go mad after CSocket or CAsyncSocket if you will try to make a server, you will get many many assertions and illegal operations, I have finally made my own CSocket class which encapsulates all winsock functions. The reason of all assertion and illegal operations you may be facing in future are:

1) CSocket creates a window which receives window messages, and creates map of sockets and which really troubles us a lot
2) both CAsyncSocket and CSocket are not threadsafe, you create one object in one thread but you can not directy access it from another thread
3) Implementing timeout is another great headque with both these classes
4) closing sockets leads to illegal operations sometimes.

For single threaded applications, these two classes are good choice, but for multithreaded they are the worst choice. Everyone uses winsock.h but no one uses CSocket.

-Akash Kava
0
 
mnashadkaCommented:
I suspect your problem is that you are using the same CSocket multiple times (you are probably getting the violation the second time through). CSocket must be cleared out after each use: call Close and then Detach. CSocket needs to make sure that the m_hSocket data member is empty when it resets it on the next socket call. When you allocate it dynamically, you're actually creating a different object (with a different m_hSocket data member), which is why it works. Hope this helps.
0
 
ackavaCommented:
no mnashdka , carefully read his code, there is no where he has used CSocket multiple times, as the object is in scope of CDialog , there is no need for Detach or Close..

Please read carefully that while doing dynamically it doesnt give any error, the object is one only.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
mnashadkaCommented:
ackava, the error that is being pointed to is the one that says that m_hSocket has been used before, and there's no way that m_hSocket would have been used before if he's creating a new object each time.  OnAccept will be called for each client, so if there is more than one client during the entire running of the program, it will die.
0
 
kender_aAuthor Commented:
Hello Akava,

Thanks for your response!

It quite probable that OnAccept() callback is called from another thread. Is there a function in Win32 API to retreive a thread handle (I'd like to make an experiment to be sure)?

Thank you,
Kender

P.S. The culprit socket is not used twice ( I have chesked it. )
0
 
ackavaCommented:
Well you can use AfxGetThread() etc, but remember OnAccept call back is not called from another thread, infact async socket creates a window and which receives notifications, so most probably OnAccept is called in same thread, but before Accept of CSocket or CAsyncSocket is called, in the begining it does some checks like ASSERT_VALID etc in these checks static objects fails.
0
 
kender_aAuthor Commented:
Hello Akava:

I have used AfxGetThread() in the CSocket's OnAccept() method, and in the main thread of the app - InitInstance(). In both cases AfxGetThread() returns the same value, but it's always negative. Is it okay?

Also I have noitced, that my app creates an additional thread. (It's not created by my code, also common dialogs and such are not used.)

Sincerely,
Kender
0
 
ackavaCommented:
Kender, Thread ids are unsigned integer, they arent basically negative, I think you must be using integer to represent its value you do something like this

CString strNumber;
strNumber.Format("%u",nID);
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now