Solved

A CSocket question.

Posted on 2002-07-20
8
942 Views
Last Modified: 2013-11-20
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
Comment
Question by:kender_a
  • 4
  • 2
  • 2
8 Comments
 
LVL 1

Accepted Solution

by:
ackava earned 150 total points
ID: 7166521
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
 
LVL 8

Expert Comment

by:mnashadka
ID: 7166996
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
 
LVL 1

Expert Comment

by:ackava
ID: 7167076
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
 
LVL 8

Expert Comment

by:mnashadka
ID: 7167138
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
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 1

Author Comment

by:kender_a
ID: 7167674
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
 
LVL 1

Expert Comment

by:ackava
ID: 7167762
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
 
LVL 1

Author Comment

by:kender_a
ID: 7176631
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
 
LVL 1

Expert Comment

by:ackava
ID: 7176986
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

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
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.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

747 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

9 Experts available now in Live!

Get 1:1 Help Now