Solved

A CSocket question.

Posted on 2002-07-20
8
1,023 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 
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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
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.
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…

726 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