我想做一个socket服务端,用于接收从多个客户端发过来的讯息,然后开始用FTP下载文件。
目前的做法流程如下:UI起来后,开启一个socket的线程,等待客户端的信息,当接收到第一个客户端的信息后,就开始使用FTP下载文件。但是发现,当第一个客户端连接进来,服务端开始下载文件后,服务端就在等着当前的FTP完成,无法再接收新的客户端的请求。
我想是不是FTP也需要用线程来完成?如果是FTP线程在文件下载结束后如何自动关闭,并通知到socket线程?还是说有别的很好的解决方法? total的,请各位指教,谢谢

解决方案 »

  1.   

    你要使用多线程技术了。另外,你可以使用完成端口(前涉器),或者使用wsa函数解决。
      

  2.   

    对了,服务器,一般很少使用ui的,你可以将服务器做成service,ui程序可以从service程序里面取一些信息,或者发布指令等(IPC范畴)。
      

  3.   

    谢谢2楼的,请问是FTP也开线程来做吗?还是别的?
    socket线程如果用异步的方法可以吗?有点糊涂的。
      

  4.   

    楼主,你说的我有点不是很明白,你说的FTP,是给客户端用来下载文件的,还是服务端用来从别的地方下载文件到服务器端?
    你这个FTP是单独的软件?
      

  5.   

    不好意思各位,是这样的:多个客户端会发消息给服务端,用于请求使用服务器端的文件,服务端接收到后如果发现当前请求的文件不存在,就开启FTP去别的地方下载文件到服务器端。
    目前的做法会产生阻塞,当socket线程开启FTP下载文件后,就无法响应后来的连接请求了。
      

  6.   


    你自己写的ftp下载? 如果你是阻塞处理的那就没办法了。只能改进的你的处理机制。一般ftp都用的网上开源的那个修改的。不会出现你说的问题。如果你说的多客户端不是很多。那你可以单独起线程做这个。不过还是很恶心的。
      

  7.   

    9#,
    我也是不想恶心单独起线程来做,所以才发帖过来问,看有没有别的解决方法啊。
    异步socket可以吗?在socket那边改不知道能不能解决这个问题,再有你说要改进出来机制,该如何改进呢,请多多指教哦
      

  8.   

    我知道我的问题在哪,但是不知道如何去改。
    就是当第一个客户端要求服务器开FTP去下载文件(size > 10G)后,服务器就停在那边了,等FTP完成才会跳出循环(如果不等的话,是否有其他办法知道FTP文件已经下载完成,或是FTP下载出问题了呢?),再响应其他客户端的请求,但是我想的是服务器端能实时响应,并且告诉客户端当前状态(这个文件不在,或是这个文件正在FTP下载中)请各位了解的,知道的,多多指点,谢谢
      

  9.   

    最好不要设计成单线程,或者一个串行化的处理。至少要支持并发处理。 FTP应该独立处理。有现成的代码的话,可以做成单独的下载线程,但是似乎大大的增加代码的复杂度,容易出错。建议做成独立进程的形式。 也就是做一个ftp.exe(或者直接利用windows的ftp.exe),下载时直接CreateProcess来调用下载进程。 这样子的好处是:免掉了单独线程的复杂性;进程的资源利用和释放率能得到保证;就算ftp过程中出错也不影响主服务;工作量少而且可靠。当然,你还需要处理一下下载完成后的通知问题。 如果是自己的代码的话,那么可以定时发个广播消息,通知下下载进度,以及下载完成,或者错误代码等。 如果是利用windows的ftp.exe,可以只能定时检查些文件属性以判断是否完成了。socket也要更改下,至少能同时支持多个客户。 并且不能让客户等待ftp完成。如果的例子,下载的东西可能10G,让客户等待的话,客户端可能长时间陷入假死的状况,并且不知道原因(因为没有反馈信息)。
    良好的处理是:不论何种情况,立刻迅速的给客户端一个回馈。如:
    1. "OK", "文件可用。"
    2. "FAIL 1", "文件不可用,正尝试获取,大约需要%d小时%d分钟,请耐心等候。"
    3. "FAIL 2", "文件不可用,已经尝试获取但失败,请报告管理员,或者尝试其他的资源。"立刻让客户了解结果是很重要的,并且不会让下一个客户一直阻塞在等待状态。
      

  10.   

    谢谢12#,我想做的就是和你说的那样。
    不好意思,再请教下,socket部分该如何修改?
    我的UI只开了一个socket线程,然后在里面用accept方法来支持多个连接,现在看起来这样也是不行的,如下代码:
    UINT StartSocketServer(LPVOID lParam)
    {
    //初始化socket       
            
    while(1)
    {
    if(!aSocket.Accept(serverSocket))
    {
    continue;
    }
    else
    {
    char szRecvMsg[256] = {0};
    char szOutMsg[256] = {0};

    serverSocket.Receive(szRecvMsg, 256);
    sprintf(szOutMsg, ">>>Receive PN info: %s \r\n", szRecvMsg);
    aDlg->m_clog.SetSel(-1, -1);
    aDlg->m_clog.ReplaceSel(szOutMsg);

    int r;
    r = aDlg->CheckPN(szRecvMsg); //检查PN号码是否可以使用
    switch(r)
    {
    case 0:
    serverSocket.Send("PNCHECKPASS", 11);
    break;
    case 1:
    serverSocket.Send("PNCHECKFAIL", 11);
    break;
    case 2:
    serverSocket.Send("SERVERWASDOWNLOADING", 20);
    //start FTP to download file
    aDlg->m_pFtpConnection = NULL;
    try
    {
    //connect to ftp
    aDlg->m_pFtpConnection = aDlg->m_Session.GetFtpConnection(aDlg->c_nasip, "anonymous", "[email protected]", INTERNET_INVALID_PORT_NUMBER);
    ......
    //close ftp, but keep internet session
    aDlg->m_pFtpConnection->Close();
    if(aDlg->m_pFtpConnection != NULL)
    delete aDlg->m_pFtpConnection;
    }
    catch(CInternetException *pEx)
    {
    pEx->ReportError(MB_ICONEXCLAMATION);
    aDlg->m_pFtpConnection = NULL;
    pEx->Delete();
    }
    serverSocket.Send("DOWNLOADFINISH", 17);
    break;
    case 3:
    serverSocket.Send("SERVERWASDOWNLOADING", 20);
    //wait until download finish
    while(w) 
    {
    for(int i=0; i<10; i++)
    if(aDlg->cdpn[i].CompareNoCase("") == 0)
    w = FALSE;
    else
    Sleep(30000);
    }
    serverSocket.Send("DOWNLOADFINISH", 17);
    break;
    default:
    break;
    }
    serverSocket.Close();
    }
    }

    aSocket.Close();
    serverSocket.Close();

    return 0;
    }
      

  11.   

    socket部分是不是修改成原socket线程做监听线程,当有连接进来再开客户端连接线程呢?
    如果把socket部分独立开来做,在UI起来后,再call socket起来,再做多客户端连接线程?貌似和上面一样,换汤不换药结了,结了。
      

  12.   

    如果使用MFC的话,socket的使用例子可以参考MSDN里面的例子:CHATTER和CHATSRVR。 多线程socket可以参考MSDN例子MultiSoc。建议阅读知识库:Q193101;175668