CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 17

Thread: Problem with winsock

  1. #1
    Join Date
    Mar 2004
    Posts
    382

    Problem with winsock

    I have a class which handels TCP/IP communication via a winsock, and I've got it to working for the most part ( I'm able to connect to the server and communicate with it). My application is a client application. First let me show you a very basic idea of what my socket class looks like:

    Code:
    // Header file
    #include <stdio.h>
    #include "winsock2.h"
    class MYSOCKET
    {
    private:
    	static char m_DestIP[16];		
    	static SOCKET m_socket;	
    public:
                    MYSOCKET();
                    bool Connect();
    }
    
    // Implementation File
    #include "MYSOCKET.h"
    
    bool MYSOCKET::Connect()
    {
                   // Initialize Winsock.
        WSADATA wsaData;
        int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
        if ( iResult != NO_ERROR )
            printf("Error at WSAStartup()\n");
    
        // Create a socket.
        m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
    
        if ( m_socket == INVALID_SOCKET ) {
            printf( "Error at socket(): %ld\n", WSAGetLastError() );
            WSACleanup();
            return false;
        }
    
        // Connect to a server.
        sockaddr_in clientService;
    
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        clientService.sin_port = htons( 27015 );
    
        if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
            printf( "Failed to connect.\n" );
            WSACleanup();
            return false;
        }
        return true;
    }
    There are more methods in the class, but they are not important in this case. Anyway, I got this code straight from microsfts websiste:
    Microsoft code and it works fine when the server is on. But, once I turn the server off, when I call the connect method twice or three times back to back, I get an error message and the application shuts down. I get the error message when I'm running the release version of the application. It's the same message you get when any windows application hangs up and the error message pops up asking you to send an error report to microsoft. But, when I run the debug version of the code, nothing happens. I can call connect as many times as I want back to back, and it will just keep on trying to re-connect, which is the behavior that I want.

    By the way, the constructor and destructor don't do anything, and before I call connect(), I just creat an object
    Code:
      MYSOCKET mySocket
    and that's it, nothing else. Does anyone know a solution to this problem?

    As for the project settings, I havn't changed anything to the default settings other then adding the library WS2_32.lib both to the release and debug build, which is necessary for winsock2.

    As for the error message, when I click on debug, I get the following message "Unhandled exception at 0x73dd1351 (MFC42.DLL) in MyApp.exe: 0xC0000005: Access violation reading location 0x00000429." and the part of the Disassembly code where the error occurs is the following:

    --- map_pp.cpp -----------------------------------------------------------------

    CMapPtrToPtr::CAssoc*
    CMapPtrToPtr::GetAssocAt(void* key, UINT& nHashBucket, UINT& nHashValue) const
    // find association (or return NULL)
    {
    nHashValue = HashKey(key);
    nHashBucket = nHashValue % m_nHashTableSize;

    if (m_pHashTable == NULL)
    return NULL;

    // see if it exists
    CAssoc* pAssoc;
    for (pAssoc = m_pHashTable[nHashBucket]; pAssoc != NULL; pAssoc = pAssoc->pNext)
    {

    if (pAssoc->key == key)
    return pAssoc;

    }
    return NULL;
    }


    73DD1350 push esi
    73DD1351 mov esi,dword ptr [ecx+4] <<<<<<<< Error here >>>>>>>>>>>
    73DD1354 test esi,esi
    73DD1356 push edi
    void* CMapPtrToPtr::GetValueAt(void* key) const
    // find value (or return NULL -- NULL values not different as a result)
    73DD1357 je CMapPtrToPtr::GetValueAt+2Ch (73DD137Fh)
    {
    if (m_pHashTable == NULL)
    73DD1359 mov edi,dword ptr [esp+0Ch]
    73DD135D xor edx,edx
    73DD135F mov eax,edi
    73DD1361 shr eax,4
    73DD1364 div eax,dword ptr [ecx+8]
    return NULL;

    Thanks in advance.
    Last edited by kodeguruguy; June 22nd, 2004 at 05:39 PM.

  2. #2
    Join Date
    May 2000
    Location
    KY, USA
    Posts
    18,652
    [Moved thread]

  3. #3
    Join Date
    Feb 2002
    Posts
    5,757
    Comment out the instantiation of the winsock wrapper class. Does the application run okay?

    Kuphryn

  4. #4
    Join Date
    Mar 2004
    Posts
    382
    Originally posted by kuphryn
    Comment out the instantiation of the winsock wrapper class. Does the application run okay?

    Kuphryn
    Do you mean the following part of the code?
    Code:
    SOCKET m_socket;
    I put that in the post by accident. m_socket is a member of the class, and I didn't have that in my class. Is that what you're talking about? If yes, that part was never in my code, I just had it on the post by accident, so that's not a problem. If no, can you be more specific on what you're talking about?

    Thanks for you help

  5. #5
    Join Date
    Feb 2002
    Posts
    5,757
    Compile the application without instantiating any object of type winsock wrapper. Does the application run okay?

    Kuphryn

  6. #6
    Join Date
    Mar 2004
    Posts
    382
    Originally posted by kuphryn
    Compile the application without instantiating any object of type winsock wrapper. Does the application run okay?

    Kuphryn
    If I don't have a winsock object, how can I communicate with the server?

    Even if I don't change anything in my code, the code compiles fine and everything functions properly, it only crashes if I have the server off-line and I try to connect to it repeatedly. After about 3 connect attempts, I get the error message. But, if I have the server on-line, I can connect to it just fine without a problem and communicate with it.

  7. #7
    Join Date
    Aug 2001
    Location
    Stockholm, Sweden
    Posts
    1,664
    You should close the socket when the connect() fails... But that doesn't create this problem (I think). I hope you don't use this object from different threads.

    You get an access violation in MFC. If you backtrace to where you call MFC (see the callstack or context in the debugger), you should find the bug. To me, it looks like you do something more with the object even though the connect() failed. Take a closer look at your code and find out from where the access violation comes (in the call-stack).
    Last edited by j0nas; June 22nd, 2004 at 04:45 PM.

  8. #8
    Join Date
    Mar 2004
    Posts
    382
    Originally posted by j0nas
    You should close the socket when the connect() fails... But that doesn't create this problem (I think). I hope you don't use this object from different threads.

    You get an access violation in MFC. If you backtrace to where you call MFC (see the callstack or context in the debugger), you should find the bug. To me, it looks like you do something more with the object even though the connect() failed. Take a closer look at your code and find out from where the access violation comes (in the call-stack).
    If connect fails, there's no point in my closing the socket. This did cross my mind also, and I did try it even though I knew it would not make any sense, but it made no difference.

    When you say "it looks like you do something more with the object even though the connect() failed", what object are you talking about? Are you talking about the MYSOCKET object? If that's the case, I'm not. Let me give a little more detail what I'm doing. Here's my connect method with some additional code
    Code:
     
    bool MYSOCKET::Connect(CString *ErrorMsg, char* DestIP, UINT32 UnitId)
    {
    	ErrorMsg->Empty();
    
    	for(int i = 0; i < 16; i++)								// Copy destination IP Address
    		m_DestIP[i] = DestIP[i];
    
    	// Initialize Winsock.
        WSADATA wsaData;
        int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
        if ( iResult != NO_ERROR ) {									
    		ErrorMsg->Format(_T("Error at WSAStartup()"));
    		return false;
    	}
    
        // Create a socket.
        m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
    
        if ( m_socket == INVALID_SOCKET ) {
    		ErrorMsg->Format(_T("Error at socket(): %ld\n"), WSAGetLastError());
            WSACleanup();
            return false;
        }
    
        // Connect to a server.
        sockaddr_in clientService;
    
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr( m_DestIP  );	
        clientService.sin_port = htons( 5678 );						// Port # = 5678
    
        if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
    		ErrorMsg->Format(_T("Failed to connect."));
            WSACleanup();
            return false;
        }
    	return true;
    }
    That's the whole thing. The UnitId item in the argument is nothing, so don't worry about that.

    I have three dialogs, each one derived from CDialog. Each dialog has a MYSOCKET member m_socket. That is why I have the members of MYSOCKET as static so even though I have three different MYSOCKET objects, there's only one MYSOCKET::m_socket object, which is the SOCKET object I use to communicate with the server. But, I call the connect method from only one dialog. On one of the dialogs I have a connect button with the message handler OnBtnConnect. The message handler calls m_socket.connect(). If the call returns false, I use PostMessage(ERROR) to call the hanlder for a user defined message. The message handler does nothing more then call connect again. So all I'm doing is just calling connect over and over again.

    It's really strange because as I mentione before, when I run the debug version, everything works fine, but when I run the release version, I get this problem.

    One more thing, for the second thing you mentiond:
    You get an access violation in MFC. If you backtrace to where you call MFC (see the callstack or context in the debugger), you should find the bug. To me, it looks like you do something more with the object even though the connect() failed. Take a closer look at your code and find out from where the access violation comes (in the call-stack).
    I just looked at the call stack, and this is what I got:
    > MFC42.DLL!CWnd::OnAmbientProperty(COleControlSite * pSite=0x00327480, long dispid=-709, tagVARIANT * pvar=0x0012ead4) Line 32 + 0xb C++
    MFC42.DLL!COleControlSite::XAmbientProps::Invoke(long dispid=-709, const _GUID & __formal={...}, const _GUID & __formal={...}, unsigned short wFlags=2, tagDISPPARAMS * pDispParams=0x0012eac4, tagVARIANT * pvarResult=0x0012ead4, const _GUID & __formal={...}, const _GUID & __formal={...}) Line 1773 + 0x19 C++
    MFC42.DLL!COleDispatchDriver::InvokeHelperV(long dwDispID=-709, unsigned short wFlags=2, unsigned short vtRet=11, void * pvRet=0x0012eb98, const unsigned char * pbParamInfo=0x00000000, char * argList=0x0012eb50) Line 345 + 0x26 C++
    MFC42.DLL!COleDispatchDriver::InvokeHelper(long dwDispID=-709, unsigned short wFlags=2, unsigned short vtRet=11, void * pvRet=0x0012eb98, const unsigned char * pbParamInfo=0x00000000, ...) Line 484 C++
    MFC42.DLL!COleDispatchDriver::GetProperty(long dwDispID=-709, unsigned short vtProp=11, void * pvProp=0x0012eb98) Line 488 + 0x16 C++
    MFC42.DLL!COleControl::GetAmbientProperty(long dwDispID=-709, unsigned short vtProp=11, void * pvProp=0x0012eb98) Line 1032 C++
    MFC42.DLL!COleControl::AmbientUserMode() Line 1105 + 0x10 C++
    cwui.ocx!24049a80()
    cwui.ocx!240f86c1()

    It doesn't make much sense to me. How would I interpret this?

    Also, on the output window I get the follwoing error message:

    The thread 'Win32 Thread' (0x71c) has exited with code 0 (0x0).
    Unhandled exception at 0x73e2e075 (MFC42.DLL) in MyApp.exe: 0xC0000005: Access violation reading location 0x00000000.

    so it seems that it is a access violation, but how can I trace it?
    Thanks for your help
    Last edited by kodeguruguy; June 22nd, 2004 at 05:56 PM.

  9. #9
    Join Date
    Aug 2001
    Location
    Stockholm, Sweden
    Posts
    1,664
    Ok, so all calls are coming from the same thread (the UI thread)?

    Backtracking or backtracing is when you look backwards (move up) in the call stack--from the crash, to where it originates.

    If you hit "Debug" when it crashes (in release or debug mode), the default installed debugger starts (in my case DevEnv (.NET2002)) and breaks on the problem line. There is a window somewhere in the IDE that shows a "Call Stack". This call stack is a list of previous functions calls. An yellow arrow points on current entry (at top) in the call stack. This is the active function. All previous functions are shown below, in order. So, if your call stack looks like this:
    Bar() <-- current
    Foo()
    Main()
    it means that the crash happened in Bar(), and Bar() was called from Foo(), which was called from Main().

    Very often, a crash will actually occur in a library, even though it originates from a bug in your own code (the client that uses the lib). Also, very often it crashes in a system DLL (ntdll.dll for instance), then you don't have source code or perhaps not even a function name, but you can still backtrace to see who initiated the fault by looking in the call stack. This is very very useful technique for finding bugs.

    One problem in your case is that it only happens in Release built. This is luckly also very common. In order to find the function (see its name in the call stack) that causes the crash in MFC, you have to compile with debug symbols. You can still compile for Release, but make sure Debug Information is enabled (/Zi).

  10. #10
    Join Date
    Mar 2004
    Posts
    382
    Originally posted by j0nas
    Ok, so all calls are coming from the same thread (the UI thread)?

    Backtracking or backtracing is when you look backwards (move up) in the call stack--from the crash, to where it originates.

    If you hit "Debug" when it crashes (in release or debug mode), the default installed debugger starts (in my case DevEnv (.NET2002)) and breaks on the problem line. There is a window somewhere in the IDE that shows a "Call Stack". This call stack is a list of previous functions calls. An yellow arrow points on current entry (at top) in the call stack. This is the active function. All previous functions are shown below, in order. So, if your call stack looks like this:
    Bar() <-- current
    Foo()
    Main()
    it means that the crash happened in Bar(), and Bar() was called from Foo(), which was called from Main().

    Very often, a crash will actually occur in a library, even though it originates from a bug in your own code (the client that uses the lib). Also, very often it crashes in a system DLL (ntdll.dll for instance), then you don't have source code or perhaps not even a function name, but you can still backtrace to see who initiated the fault by looking in the call stack. This is very very useful technique for finding bugs.

    One problem in your case is that it only happens in Release built. This is luckly also very common. In order to find the function (see its name in the call stack) that causes the crash in MFC, you have to compile with debug symbols. You can still compile for Release, but make sure Debug Information is enabled (/Zi).
    First of all, I really appreciate all your help.

    Yes all calls are coming from the same thread.

    As for compiling with debug symbols, how would I do that? Is that something I set from the project->settings window? And what exactly does compiling with debug symbols do if you don't mind me asking.

    By the way, I'm using Visual Stuido 6.0 in case it make any difference.

    Thanks again.

  11. #11
    Join Date
    Feb 2003
    Location
    Bangalore, India
    Posts
    1,354
    Though I can't offer much help to your original problem, there are a few things which I'd like to point out to, regarding your winsock code.
    Originally posted by kodeguruguy
    If connect fails, there's no point in my closing the socket. This did cross my mind also, and I did try it even though I knew it would not make any sense, but it made no difference.
    No, it does make difference. When you call socket() it "creates" a socket...and you are only given a handle to the socket descriptor. When you create a socket, some resource are allocated to it. So when you destroy the handle without using closesocket(), you won't have a reference to the resource that is created, thus resulting in a memory leak. So you should have one closesocket() call for every socket().

    Second thing is about initializing. You don't have to call WSAStartup() at every call to connect. Though there is nothing wrong, it is unnecessary. You only have to do it once and when you know that you are done with winsock call WSACleanup().You can move the init part to the constructor and the clean-up part to the destructor.

    I'm also in favor of calling socket() only once for a connection that is established or to be established. You can then close the socket once you are done with the connection.

    Once you get the answer to your problem please participate us with it.

    Good Luck!!

    Even if our suggestions didn't help, please post the answer once you find it. We took the effort to help you, please return it to others.

    * While posting code sections please use CODE tags
    * Please check the codeguru FAQ and do a little search to see if your question have been answered before.
    * Like a post, Rate The Post
    * I blog: Network programming, Bible

    I do all things thru CHRIST who strengthens me

  12. #12
    Join Date
    Jun 2004
    Posts
    17
    i notice yr crash happened in the midst of some ActiveX code.
    uhuhuhuuhuhuhuhu. shiver. what part of yr code uses ActiveX?
    if you want flaky untraceable bugs & incomprehensible dynamic linking errors, why not just use visual basic? if you need to use com servers in yr program, i wld suggest doin it longhand w/ the C api.

    also why are you using MFC? its another technology that isnt particularly robust or useful imho.

    :-)

  13. #13
    Join Date
    Mar 2004
    Posts
    382
    Originally posted by Mathew Joy
    Though I can't offer much help to your original problem, there are a few things which I'd like to point out to, regarding your winsock code.
    No, it does make difference. When you call socket() it "creates" a socket...and you are only given a handle to the socket descriptor. When you create a socket, some resource are allocated to it. So when you destroy the handle without using closesocket(), you won't have a reference to the resource that is created, thus resulting in a memory leak. So you should have one closesocket() call for every socket().

    Second thing is about initializing. You don't have to call WSAStartup() at every call to connect. Though there is nothing wrong, it is unnecessary. You only have to do it once and when you know that you are done with winsock call WSACleanup().You can move the init part to the constructor and the clean-up part to the destructor.

    I'm also in favor of calling socket() only once for a connection that is established or to be established. You can then close the socket once you are done with the connection.

    Once you get the answer to your problem please participate us with it.

    Good Luck!!

    I did add the closesocket() function to my class, but that didn't seem to help much, but I'll try it one more time.

    As for WSAStartup and WSACleanup, I did use both, and it didn't make any difference.

    I'm also in favor of calling socket() only once for a connection that is established or to be established. You can then close the socket once you are done with the connection.
    I did this also, I called socket() only once, and for every time connect failed, I would only call connect(), but I would still have the same problem.

  14. #14
    Join Date
    Mar 2004
    Posts
    382
    Originally posted by jono
    i notice yr crash happened in the midst of some ActiveX code.
    uhuhuhuuhuhuhuhu. shiver. what part of yr code uses ActiveX?
    I acutally have a third party add-on software which allows me to use some additional controls and graphs. It's a pretty well know company, but their controls require ActiveX.

    if you want flaky untraceable bugs & incomprehensible dynamic linking errors, why not just use visual basic? if you need to use com servers in yr program, i wld suggest doin it longhand w/ the C api.
    All I need is a simple program that communicates with a micro-controller which supports TCP/IP connection.

    also why are you using MFC? its another technology that isnt particularly robust or useful imho.
    Your one of the very few people I have heard saying this. I think because the thread was moved to another forum instead of the Visual C++ programming forum. Anyway, I like MFC. Simple, straight forward and can be very robust if you know what you're doing.

    Thanks

  15. #15
    Join Date
    Aug 2001
    Location
    Stockholm, Sweden
    Posts
    1,664
    Originally posted by kodeguruguy
    First of all, I really appreciate all your help.

    Yes all calls are coming from the same thread.

    As for compiling with debug symbols, how would I do that? Is that something I set from the project->settings window? And what exactly does compiling with debug symbols do if you don't mind me asking.

    By the way, I'm using Visual Stuido 6.0 in case it make any difference.

    Thanks again.
    Yes, in VC6 you change compiler/link options in Project->Settings... menu. Do this:
    1. Go to project settings
    2. Go to tab Link
    3. Make sure it is for Release mode (Settings for
    4. In Category dropdown list, select General
    5. There are five different checkboxes below... One of them says "Generate debug info". This is normally unchecked in Release. Check it.
    6. Rebuild

    Sometimes the code layout will be so different from the code you actually wrote, so the debugger won't find all symbols (function names etc). This is due to compiler optimization. You may need to disable optimization. You disable it from the C/C++ tab in Project settings (Category: Optimizations). Please note that the bug may not appear at all after optimization is disabled :-(

    Debug symbols are (symbolic) names for addresses. In assembler, a function call looks something like "CALL 0x0050a3f0". With debug symbols, the address 0x0050a3f0 will show up as the actual function name.

    I hope you're able to find the problem now.

    Good luck,
    Jonas

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)