下面是用到的其中一个函数
现在是运行的过程中,一旦accept()出现问题的话,程序就阻塞了。
也不知道应该如何去设置超时时间,先前设定的也没有用。
于是请教诸位了。也查过一些网页,想问问看看能不能不用 非阻塞socket的程序,就能解决这个问题。
//Upload用来向服务器上载一个文件,调用前需要设置属性m_IdeaID,m_TaskID
//这时客户机是Socket Server,服务器是Socket Client
BOOL CSystemStatus::Upload(CString strFilename)
{
//先判断能否打开文件
CFile myFile;
if(!myFile.Open(strFilename, CFile::modeRead | CFile::typeBinary))
{
AfxMessageBox("无法打开文件:"+strFilename);
return FALSE;
} //服务器IP地址
CString strServerIP = GetServerIP();
//客户端IP地址
CString strClientIP = GetClientIP(); //向服务器登记需要上载的文件信息
TransferFile upInfo;
upInfo.IdeaID = m_IdeaID;
upInfo.TaskID = m_TaskID;
upInfo.Directory = m_Directory;
upInfo.Sender = "Client"; //客户机发送
upInfo.SendIP = strClientIP;
upInfo.Receiver = "Server"; //服务器接收
upInfo.RecIP = strServerIP;
upInfo.FileName = GetFileName(strFilename); //上载的文件名,这个文件名含有路径,这里需要把路径去掉
upInfo.Flag = "0"; //设置未处理标志,等待服务器处理
CTransferFilesDB transfer;
transfer.ExecuteInsert(upInfo); //存入数据库 AfxSocketInit(NULL);
CSocket sockSrvr; 
sockSrvr.Create(PORT); // Creates our server socket
sockSrvr.Listen(); // Start listening for the client at PORT int   TimeOut=6000;   //设置发送超时6秒   
if(::setsockopt(sockSrvr,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
{   
return   0;   
}
TimeOut=6000;//设置接收超时6秒   
if(::setsockopt(sockSrvr,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){   
return   0;   
}

CSocket sockRecv;
sockSrvr.Accept(sockRecv); // Use another CSocket to accept the connection


TimeOut=6000;   //设置发送超时6秒   
if(::setsockopt(sockRecv,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR)
{   
return   0;   
}
TimeOut=6000;//设置接收超时6秒   
if(::setsockopt(sockRecv,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){   
return   0;   
} if(sockRecv==INVALID_SOCKET)
{
//错误处理
AfxMessageBox("超时错误!");
return FALSE;
}
AfxMessageBox("接收连接成功");
int myFileLength = myFile.GetLength(); // Going to send the correct File Size sockRecv.Send(&myFileLength, 4); // 4 bytes long

char sendBuf[MM];
for(int i=0;i<=myFileLength;i+=MM)
{
myFile.Read(sendBuf, sizeof(sendBuf));
sockRecv.Send(sendBuf,sizeof(sendBuf)); //Send the whole thing now
Sleep(10);
}
if(myFileLength%MM!=0)
{
myFile.Read(sendBuf, myFileLength%MM);
sockRecv.Send(sendBuf,myFileLength%MM);
Sleep(10);
}
myFile.Close(); sockRecv.Close();
return TRUE;
}

解决方案 »

  1.   

    通常accept阻塞直到有客户端连接服务器可以考虑其他网络IO模型:
    选择套接字
    异步选择套接字
    事件选择套接字
    重叠套接字
      

  2.   

    可以解决
    我试验了一下
    CAsyncSocket m_SocketServer;
    Csocket m_pSocket;
    int TimeOut=6000;
    oldtime = GetTickCount();
    while (GetTickCount() - oldtime < TimeOut)
    {

    bAccept = m_SocketServer.Accept(*m_pSocket);
    if (bAccept)
    {
    /////成功处理
                    break; }
    else
    {
    continue;
    }
    }
      

  3.   

    m_SocketServer 不一定是CAsyncSocket 
    是一个非阻塞就可以
      

  4.   

    标准的多线程并发模型就是阻塞在accept上面,然后子线程再recv,以及其它操作.主线程会循环accept,并建立子线程.你为何不能阻塞在accept上面呢?作为 server那谁来监听连接?
      

  5.   


    大人能不能更详细一些。
    是说用多线程么?
    这个“不能阻塞在accept上面”是什么意思?
      

  6.   


    哦,我看快了点,误解你的意思了。现在是运行的过程中,一旦accept()出现问题的话,程序就阻塞了。 
    也不知道应该如何去设置超时时间,先前设定的也没有用。 
    于是请教诸位了。 accept出现什么问题,导致你如此阻塞?描述一下。
      

  7.   

    开一条专门ACCEPT线程,可以用WSAEventSelect来查询是否有连接请求初始化时添加        //创建事件句柄
    m_hAcceptEvent = WSACreateEvent();
    if(m_hAcceptEvent == NULL)
    {
    DeInitServer();
    return FALSE;
    }
            //将监听的SOCKET设置EVENSELCT模型
    nCode = WSAEventSelect(m_ServSock, m_hAcceptEvent, FD_ACCEPT);
    if(nCode == SOCKET_ERROR)
    {
    DeInitServer();
    return FALSE;
    }接受连接的线程 DWORD WINAPI AcceptThread(LPVOID lParam)
    {
         SOCKET ListenSocket = (SOCKET)lParam;//这个参数是你的监听SOCKET
         
         WSANETWORKEVENTS WSAEvents;
              while(WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
         {
              if (WSA_WAIT_TIMEOUT != WSAWaitForMultipleEvents(1, &g_hAcceptEvent, FALSE, 0, FALSE))
              {
                   WSAEnumNetworkEvents(ListenSocket, g_hAcceptEvent, &WSAEvents);
                   if ((WSAEvents.lNetworkEvents & FD_ACCEPT) && (0 == WSAEvents.iErrorCode[FD_ACCEPT_BIT]))
                   {
                        //处理并接受就是了
                        AcceptConnection();
                   }
              }
         }
         
         return 0;
    }