VerySource

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1173|回复: 7

求助:DLL中调用Socket出现ASSERT问题!

[复制链接]

1

主题

2

帖子

3.00

积分

新手上路

Rank: 1

积分
3.00
发表于 2020-3-15 19:30:02 | 显示全部楼层 |阅读模式
在一个WEB应用服务器程序里,专门负责处理Browser客户端的请求,当接收到用户下载文件的请求后,调用一个DLL的函数去文件服务器获取所请求的文件。
文件传输的函数是用Socket实现的。在传第一个文件的时候没问题,当第二个下载请求到来后,WEB服务器调DLL里的函数出错了,

出错的地方在sockcore.cpp
的BOOL CAsyncSocket::AsyncSelect(long lEvent)方法:

ASSERT(pState->m_hSocketWindow != NULL);

查了网上一些帖子,说是多线程调用Socket出的问题,要使用Attach和Detach
来处理。我的Socket调用是封装在一个DLL里的,如下:

请问该如何修改?!!

int getRemoteFile(CString strIP, CString fName,int port)
{

        int nRet = 0; // return value

        AfxSocketInit(NULL);//should comment this line?

        CSocket sockClient;
        sockClient.Create();

        sockClient.Connect( strIP, port);

        int dataLength, cbBytesRet, cbLeftToReceive;
        // pointer to buffer for receiving data
        // (memory is allocated after obtaining file size)
        BYTE* recdData = NULL;
   
        CFile destFile;
        CFileException fe;
        BOOL bFileIsOpen = FALSE;
   
                // open/create target file that receives the transferred data
   
        if( !( bFileIsOpen = destFile.Open( fName, CFile::modeCreate |
                        CFile::modeWrite | CFile::typeBinary, &fe ) ) )
        {
                TCHAR strCause[256];
                fe.GetErrorMessage( strCause, 255 );
                TRACE( "GetFileFromRemoteSender encountered an error ");
                //AfxMessageBox(strCause);
                /* you should handle the error here */
        
                nRet = -1;
                goto PreReturnCleanup;
        }
   
                // get the file's size first
        cbLeftToReceive = sizeof( dataLength );
        do
        {
                BYTE* bp = (BYTE*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
                cbBytesRet = sockClient.Receive( bp, cbLeftToReceive );
        
                // test for errors and get out if they occurred
                if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
                {
                        int iErr = ::GetLastError();
                        //TRACE( "GetFileFromRemoteSite returned a socket error");
                        /* you should handle the error here */
            
                        nRet = -2;
                        goto PreReturnCleanup;
                }
        
                // good data was retrieved, so accumulate
                // it with already-received data
                cbLeftToReceive -= cbBytesRet;
        }
        while ( cbLeftToReceive > 0 );

        dataLength = ntohl( dataLength );

        // now get the file in RECV_BUFFER_SIZE chunks at a time
   
        recdData = new byte[RECV_BUFFER_SIZE];
        cbLeftToReceive = dataLength;
   
        do
        {   
                int iiGet, iiRecd;

                iiGet = (cbLeftToReceive<RECV_BUFFER_SIZE) ?
                      cbLeftToReceive : RECV_BUFFER_SIZE ;
                iiRecd = sockClient.Receive( recdData, iiGet );

                // test for errors and get out if they occurred
                if ( iiRecd == SOCKET_ERROR || iiRecd == 0 )
                {
                    int iErr = ::GetLastError();
                    //TRACE( "returned a socket error");
                    CString errMsg;
                    errMsg.Format("%d",iErr);
                    /* you should handle the error here */
            
                    nRet = -3;
                    goto PreReturnCleanup;
                }

                destFile.Write( recdData, iiRecd); // Write it
                cbLeftToReceive -= iiRecd;

        }
        while ( cbLeftToReceive > 0 );

PreReturnCleanup: // labelled "goto" destination

        delete[] recdData;        
   
        if ( bFileIsOpen )
                destFile.Close();
        // only close file if it's open (open might have failed above)
        sockClient.Detach();//detach 或许没用
        sockClient.Close();

    return nRet;
}


回复

使用道具 举报

0

主题

30

帖子

22.00

积分

新手上路

Rank: 1

积分
22.00
发表于 2020-7-28 19:00:01 | 显示全部楼层
在函数头加上
AfxManageModuleState
回复

使用道具 举报

0

主题

2

帖子

3.00

积分

新手上路

Rank: 1

积分
3.00
发表于 2020-7-28 20:15:01 | 显示全部楼层
CAsyncSocket和CSocket需要一个窗口对象做消息处理,因此你需要自己创建一个CWnd对象。具体过程你可以查一下以前的帖子,有人问过并解决了。
其实这两个类并不好用,建议你使用Winsock2的API。
回复

使用道具 举报

1

主题

2

帖子

3.00

积分

新手上路

Rank: 1

积分
3.00
 楼主| 发表于 2020-8-7 19:00:01 | 显示全部楼层
to:北冥唐

酱紫啊,可是这个DLL我是给java调用滴(就是通过JNI),所以..
好像创建CWnd对象有难度....
用Winsock2的API怎么搞捏?麻烦给段代码示例
回复

使用道具 举报

0

主题

24

帖子

19.00

积分

新手上路

Rank: 1

积分
19.00
发表于 2020-8-8 15:15:01 | 显示全部楼层
Socket API? 可以阅读《Windows网络编程》
回复

使用道具 举报

0

主题

7

帖子

7.00

积分

新手上路

Rank: 1

积分
7.00
发表于 2020-8-8 16:00:01 | 显示全部楼层
CAsyncSocket和CSocket不是线程安全的
回复

使用道具 举报

0

主题

2

帖子

3.00

积分

新手上路

Rank: 1

积分
3.00
发表于 2020-8-16 14:15:01 | 显示全部楼层
创建一个不可见的窗口即可,因为只是用它做消息处理。
to yexilove :
CAsyncSocket和CSocket的线程安全是通过CWnd做消息处理实现的。
回复

使用道具 举报

0

主题

2

帖子

3.00

积分

新手上路

Rank: 1

积分
3.00
发表于 2020-8-16 14:45:01 | 显示全部楼层
我以前也遇到过类似问题,使用CAsyncSocket和CSocket类都会出异常,最后还是用winsock套接字的api解决的问题.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|CopyRight © 2008-2023|verysource.com ( 京ICP备17048824号-1 )

快速回复 返回顶部 返回列表