Solved

A CSocket question.

Posted on 2002-07-20
8
992 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
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

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.

 
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

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Strange date stored 22 148
Define unique primary key 9 95
ffmpeg - "rtsp://...... Operation not permitted" 4 86
modThree challenge 4 96
Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
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…
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.

808 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