首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 为什么第一次连接行,第二次连接就不行了,SOCKET [无满意答案结贴,结贴人:RuanJianRenAtMSN]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • RuanJianRenAtMSN
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 揭贴率:
    发表于:2008-08-22 14:54:40 楼主
    DWORD WINAPI CFileServer::SendFile(LPVOID lp)
    {
    SEND_THREAD *m_lp = (SEND_THREAD*)lp;

        //每次包的长度
    char chLen[10];
    //返回检查包
    char chCheck[3];

    //返回值
    int intRet;
     
    CCFileManager *m_FileMgr = CCFileManager::GetFileManager();

    EnterCriticalSection(&(m_FileMgr->m_gs));
        //获得内存临时文件,
        FILE_TABLE *m_File =  m_FileMgr->GetFileList(m_lp->chFromUserName,m_lp->chToUserName);
      LeaveCriticalSection(&(m_FileMgr->m_gs));

    //对方已取消发送
    if(m_File->intIs == 4)
    {

    closesocket(m_lp->m_sock);

    m_FileMgr->DeleteFileNode(m_File);

    delete m_lp;

    return FALSE;
    }
    //计算包的个数
        int intPackCount = m_File->intPackCount;

    //包个数
    itoa(intPackCount,chLen,10);

        //发送包数量
    send(m_lp->m_sock,chLen,10,0);

    //接收返回包
    lop1:intRet = recv(m_lp->m_sock,chCheck,3,0);

    if(intRet ==  -1)
    {
    Sleep(1000);

    goto lop1;
    }
    //对方已关闭接收
    if(intRet == 0)

    //通知接收线程对方已不需要接收文件
    m_File->intIs = 3;

    closesocket(m_lp->m_sock);

    delete m_lp;

    return FALSE;
    }

    for(int i=0;i <intPackCount;i++)
    {
    //若发送方已取消发送
          if(m_File->intIs == 4)
    {
                  closesocket(m_lp->m_sock);
        //删除结点
        m_FileMgr->DeleteFileNode(m_File);

            delete m_lp;

        return FALSE;

    }
    //包长度
    itoa(m_File->intBUFSize,chLen,10);

    //发送包长
    send(m_lp->m_sock,chLen,10,0);

    //接收返回包
    lop3:
    intRet = recv(m_lp->m_sock,chCheck,3,0);

    if(intRet == -1)
    {
    Sleep(1000);

    goto lop3;
    }
           
    //发送数据包
    send(m_lp->m_sock, m_File->chBUF,m_File->intBUFSize,0);
    //接收返回包
    lop4:
    intRet = recv(m_lp->m_sock,chCheck,3,0);

    if(intRet == -1)
    {
    Sleep(1000);

    goto lop4;
    }
        //若接收客户端已关闭
    if(intRet == 0)
    {   
    //对方已取消接收
    m_File->intIs = 3;

    closesocket(m_lp->m_sock);

    delete m_lp;

    return FALSE;
    }

        EnterCriticalSection(&(m_File->gs_sec));
            //已发送
    m_File->intIs = 2;

            //可以删除内存
    delete m_File->chBUF;

    m_File->chBUF = NULL;
            //数据工作区大小清0
    m_File->intBUFSize = 0;

            //包个数自减1
    m_File->intPackCount--;

    LeaveCriticalSection(&(m_File->gs_sec));

    if(m_File->intPackCount !=0)
    {
            //挂起本地线程
    SuspendThread(m_File->m_SendHandle);
    }
    }

    AfxMessageBox("Exit Send Thread");

    closesocket(m_lp->m_sock);

    delete m_lp;

    return 0;
    }

    //接收文件
    DWORD WINAPI CFileServer::ReceiveFile(LPVOID lp)
    {
    SEND_THREAD *m_lp = (SEND_THREAD*)lp;

    //返回值
    int intRet;

    //包长
    char chLen[10];

        //返回检测包
    char chCheck[3];

    //包大小
    int intPackLen;

    //已接收的包大小
    int intHavRecv;

    FILE_PACK_TOP lptop;
    //接收文件头
    lop0:intRet = recv(m_lp->m_sock,(char*)&lptop,sizeof(FILE_PACK_TOP),0);

    if(intRet == -1)
    {
    Sleep(500);

    goto lop0;
    }

    //客户端已断开
    if(intRet == 0)
    {
    closesocket(m_lp->m_sock);

    delete m_lp;

    return FALSE;
    }
    //发送返回包
    strcpy(chCheck,"OK");

    intRet = send(m_lp->m_sock,chCheck,3,0);

    //包个数
    int intPackCount = lptop.intCount;
        //创建临时内存区
    FILE_TABLE *m_FileList = new FILE_TABLE;
        //文件名
    strcpy(m_FileList->chFileName,lptop.chFileName);
    //发送者
    strcpy(m_FileList->chFormUser,lptop.chFromUserName);
    //接收者
    strcpy(m_FileList->chToUser,lptop.chToUserName);
        //初始化临界区
    InitializeCriticalSection(&(m_FileList->gs_sec));
    //必需接收的包数量
    m_FileList->intPackCount = lptop.intCount;
        //数据还没准备好
    m_FileList->intIs = 0;

    m_FileList->chBUF = NULL;
        //数据工作区大小
    m_FileList->intBUFSize = 0;
    //发送者线程句柄NULL
    m_FileList->m_SendHandle = NULL;

    CCFileManager *m_FileMgr = CCFileManager::GetFileManager();

        //文件加入至连表
        m_FileMgr->AddFileList(m_FileList);

        //等待对方取走数据计数
    int intWaitCount;

    while( intPackCount != 0 )
    {
    ZeroMemory(chLen,10);
    //接收包长
    lop1:
    intRet = recv(m_lp->m_sock,chLen,10,0);

    if(intRet == -1)
    {
      Sleep(100);

                  goto lop1;
    }
    //若客户端关闭
    if(0==intRet)
    {
        //对方已取消发送
    m_FileList->intIs = 4;

                //用户已关闭连接
    closesocket(m_lp->m_sock);

    //删除线程函数形参
    delete m_lp;

    return 0;
    }
        //若已接收到包长
    intPackLen = atoi(chLen);

    //临时数据内存区
    m_FileList->chBUF = new char[intPackLen];
                //数据包大小
    m_FileList->intBUFSize = intPackLen;
    //已接收字节
    intHavRecv = 0;

    while((intPackLen != intHavRecv) &&

    ((CICQSApp*)AfxGetApp())->bolRuning)
    {
          lop2:
    intRet = recv(m_lp->m_sock,m_FileList->chBUF + intHavRecv,intPackLen -intHavRecv ,0);

    if(intRet == -1)
    {
    Sleep(100);

    goto lop2;
    }

    //若客户端关闭
    if(intRet == 0)
    {
    //用户已关闭连接
    closesocket(m_lp->m_sock);

    delete m_lp;

    //发送者线程存在
    if(m_FileList->m_SendHandle != NULL)
    {
    //对方已取消发送
    m_FileList->intIs = 4;

    }else //若发送者线程还没启动,则自删除结点
    {
    m_FileMgr->DeleteFileNode(m_FileList);
    }
                        //删除文件连表中的结点
    //m_FileMgr->DeleteFileNode(m_FileList);
    return 0;

    }

    intHavRecv += intRet;

    }

    //数据已准备好,通知发送者发送数据
                m_FileList->intIs = 1;

                //若对方在1分中内没取走数据则假设对方已关了客户端
                intWaitCount = 0;

    WaitExist: 
    if(m_FileList->m_SendHandle != NULL)
    {
    //唤醒发送者
    ResumeThread(m_FileList->m_SendHandle);

    }else//线程还没启动
    {
    intWaitCount++;

    if(intWaitCount <60)
    {
    Sleep(1000);

                        goto WaitExist;
    }else //若等了1分钟还没有发送服务,则退出
    {
    strcpy(chCheck,"NO");
    //发送返回包
    send(m_lp->m_sock,chCheck,3,0);

    //用户已关闭连接
    closesocket(m_lp->m_sock);

    delete m_lp;

    m_FileMgr->DeleteFileNode(m_FileList);

    return 0;
    }
    }

    intWaitCount = 0;
    lop3:
    switch(m_FileList->intIs)
    {
    case 1://等发送者取走数据
    {
    intWaitCount++;

    if(intWaitCount <60)
    {
    Sleep(200);

    goto lop3;

    }else//若在一分中内还没取走一个包就不要发送了
    {
    strcpy(chCheck,"NO");
    //发送返回包
    send(m_lp->m_sock,chCheck,3,0);

    //用户已关闭连接
    closesocket(m_lp->m_sock);

    delete m_lp;

    m_FileMgr->DeleteFileNode(m_FileList);

    return 0;

    }

    }
    break;
    case 3://对方取消了接收
    {
    strcpy(chCheck,"NO");
    //发送返回包
    send(m_lp->m_sock,chCheck,3,0);

    //用户已关闭连接
    closesocket(m_lp->m_sock);

    delete m_lp;

    m_FileMgr->DeleteFileNode(m_FileList);

    return 0;

    }
    break;
    }
    //发送返回包
    send(m_lp->m_sock,chCheck,3,0);
    //包个数减1
    intPackCount--;

    }

        //自删除结点
    m_FileMgr->DeleteFileNode(m_FileList);

    AfxMessageBox("Exit Receive Thread");

        closesocket(m_lp->m_sock);
     
        delete m_lp;

      return 0;
    }
    20  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • RuanJianRenAtMSN
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 14:56:421楼 得分:0
    以上是我的发送者也接收者服务线程,问题就是出在这两个线程中,线程已保证退出,但是第二客户端连接就失败!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • orbit
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 15:41:232楼 得分:0
    失败的原因是服务端有问题,一般服务线程都是listen+accept循环来保证对所有的客户端connect都响应,但是从你贴出的代码没有看到这一点,是不是在调用CFileServer::ReceiveFile之前listen+accept的?如果是的话就在这里下断点调试吧
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • RuanJianRenAtMSN
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 15:48:293楼 得分:0
    谢谢上面的大哥,的帮肋,是的,listen+accept是用WSAAsyncSelect驱动的,在上面已设了断点,但是第一次连接连FD_ACCEPT事件都不会发生,?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • RuanJianRenAtMSN
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 15:49:094楼 得分:0
    说错了,是第二次FD_ACCEPT事件不会发生!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jszj
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 15:57:265楼 得分:0
    有没有第二次调用accept?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • RuanJianRenAtMSN
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 16:11:066楼 得分:0
    当然有了.因为服务连接是不定的所以服务等候Connect用WSAAsyncSelect模式.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hurryboylqs
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 18:48:247楼 得分:0
    WSAGetLastError看看
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved