哪一种方法?
有异步调用的,有完成端口的,有发消息的,还有通过用select来实现单线程管理多个socket连接的.
如果在收到一个连接时就开一个线程,这种方法太土了,大型项目都不会这么做的。

解决方案 »

  1.   

    哦,顺便介绍一本书,<<winsock 网络核心编程>>,看过之后,你会对这些模型了如指掌。
      

  2.   

    哈,我忘了写地址啦:[email protected]
    最好是异步的,各位谢谢了!
      

  3.   

    参考一下我写的代码吧,多线程
    #include "ESocket.h"//*******************************************************************************//
    //服务器端代码
    ESocketServer::ESocketServer()
    {
    m_bInit = TRUE;
    m_MainSocket = 0;
    NewExchange = DefHandle; WORD wVersionRequested;
    int ret; wVersionRequested = MAKEWORD(1,1);
    ret = WSAStartup(wVersionRequested,&wsaData); if(ret != 0)
    {
    m_bInit = FALSE;
    return;
    } // The low byte is the major version and the high byte is the minor version
    if( LOBYTE(wsaData.wVersion) < 1 ) //如果主版本号小于1
    {
    WSACleanup();
    m_bInit = FALSE;
    return;
    }
    }ESocketServer::~ESocketServer()
    {
    if(m_bInit)  //m_bInit == TURE
    WSACleanup();
    }int ESocketServer::InitSvr(unsigned short port)
    {
    if(!m_bInit) return FALSE; SOCKADDR_IN sin;
    m_MainSocket = socket(AF_INET,SOCK_STREAM,0);  //建立TCP连接 if(m_MainSocket == INVALID_SOCKET)
    return FALSE;    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);     //这里必须进行转换,不然结果不对(因为ip格式是高位在后面,低位在前面)
        sin.sin_addr.s_addr = htonl(INADDR_ANY); if( bind(m_MainSocket,(LPSOCKADDR)&sin,sizeof(sin)) )
    {
    closesocket(m_MainSocket);
    m_MainSocket = 0;
    return FALSE;
    } if( listen(m_MainSocket,5) )
    {
    closesocket(m_MainSocket);
    m_MainSocket = 0;
    return FALSE;
    } return TRUE;
    }void ESocketServer::DefHandle(SOCKET skt)
    {
    //默认的仅仅是关闭新开的socket
    closesocket(skt);
    }int ESocketServer::RunLoop()
    {
    if(m_MainSocket == 0) return FALSE; SOCKET newskt;
    SOCKADDR tcpaddr;
    int len;
    len = sizeof(tcpaddr);
    memset(&tcpaddr,0,len);
    while(1)
    {
    newskt = accept(m_MainSocket,&tcpaddr,&len);
    if( newskt != INVALID_SOCKET ) 
    {
    NewExchange(newskt);
    }
    Sleep(100);
    }
    return TRUE;
    }//*******************************************************************************//
    //客户端代码
    ESocketClient::ESocketClient()
    {
    m_bInit = TRUE;
    ExchangeData = DefHandle; WORD wVersionRequested;
    int ret; wVersionRequested = MAKEWORD(1,1);
    ret = WSAStartup(wVersionRequested,&wsaData); if(ret != 0)
    {
    m_bInit = FALSE;
    return;
    } if( LOBYTE(wsaData.wVersion) < 1 )
    {
    WSACleanup();
    m_bInit = FALSE;
    return;
    }}ESocketClient::~ESocketClient()
    {
    if(m_bInit)  //m_bInit == TURE
    WSACleanup();
    }int ESocketClient::InitClient(char * IpAddr,unsigned int port)
    {
    if(!m_bInit) return FALSE; SOCKADDR_IN sin;
    m_MainSocket = socket(AF_INET,SOCK_STREAM,0);  //建立TCP连接 if(m_MainSocket == INVALID_SOCKET)
    return FALSE;    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);     //这里必须进行转换,不然结果不对(因为ip格式是高位在后面,低位在前面)
        sin.sin_addr.s_addr = inet_addr(IpAddr); if( connect(m_MainSocket,(LPSOCKADDR)&sin,sizeof(sin)) == SOCKET_ERROR )
    {
    closesocket(m_MainSocket);
    return FALSE;
    }
    return TRUE;
    }void ESocketClient::DefHandle(SOCKET skt)
    {
    //默认的仅仅是关闭新开的socket
    closesocket(skt);
    }int ESocketClient::RunLoop()
    {
    if(m_MainSocket == 0) return FALSE; ExchangeData(m_MainSocket);
    return TRUE;
    }
      

  4.   

    还有头文件
    //*********************************************************************//
    //                                                                     //
    //  并发的基于socket的服务器 (Windows Socket 1.1)                      //
    //                                                                     //
    //  Author:dah  2001/10/10                                          //
    //                                                                     //
    //*********************************************************************//#ifndef __ESOCKET__DAH__2001_10_10__
    #define __ESOCKET__DAH__2001_10_10__#include "winsock.h"//服务器策略
    //自动启动并拥有多线程功能
    class ESocketServer
    {
    public:
    ESocketServer();
    ~ESocketServer();public:
    //返回值 TRUE 为成功, FALSE 为失败
    int InitSvr(unsigned short port);   //启动服务器(事实上只能运行一次)
    int RunLoop();                      //程序主循环    static void DefHandle(SOCKET skt);  //默认处理函数
        void (* NewExchange)(SOCKET skt);   //处理新的客户端,回调函数
    private:
    int m_bInit;                        //是否已经成功初始化
    WSADATA wsaData;
    SOCKET m_MainSocket;                //主Socket(第一个被生成的)};//客户端策略
    //由用户启动线程并调用ESocketClient::Run(),Run中已经包含了while循环
    class ESocketClient
    {
    public:
    ESocketClient();
    ~ESocketClient();public:
    //返回值 TRUE 为成功, FALSE 为失败
    int InitClient(char * IpAddr,unsigned int port);
    int RunLoop();                      //程序主循环
        static void DefHandle(SOCKET skt);  //默认处理函数
        void (*  ExchangeData)(SOCKET skt); //处理新的客户端,回调函数
    private:
    int m_bInit; //是否已经成功初始化
    WSADATA wsaData;
    SOCKET m_MainSocket;                //Socket句柄
    };#endif
      

  5.   

    to gameboy999(我心迷茫):非常感谢你的关注,可我看了你的代码以后,好象不是多线程处理的,在服务器端,你accept后调用一函数,那函数是的代码可以贴出来吗?同样在客户端
    的ExchangeData()函数可以贴出来我参考一下,谢谢!
      

  6.   

    哦,我上面的模型是可以写成 并发 或者 重复 的就看回调函数写成什么样子。给你部分代码(就基于多线程的吧)
    例如服务器端
    //******************************************************************************//
    // by dah 2001/10/11
    UINT HandleLoop(LPVOID pParam)
    {
    SOCKET skt = * (SOCKET *)pParam;
    CFile file;   //针对每个用户开一个CFile即可
    FileList filelist; //初始化filelist
    InitFileList(file,filelist);    char buf[2049];
    int rval = 0;
    do
    {
    memset(buf,0,2049);
    //注:8192字节是局域网上面能一次传输的最大字节数
    rval = recv(skt,buf,2048,0);
    if(rval >0)
    {
    AnalyzePacket(skt,buf,rval,file,filelist);
    }
    Sleep(50);
    }
    while( rval >0 ); //while ( rval != 0 && rval != SOCKET_ERROR ); g_ThreadNum--; CString cs;
    cs.Format("Socket:%d ended!\r\n共有%d个客户正在运行!\r\n",skt,g_ThreadNum);
    ShowContent((LPCTSTR)cs); return 0;
    }//HandleNew可以决定是采用轮循还是并发
    void HandleNew(SOCKET skt)
    {
    AfxBeginThread(HandleLoop,&skt);
        Sleep(300);  //这里Sleep 300秒是必须的! g_ThreadNum++;
    CString cs;
    cs.Format("Socket:%d started!\r\n共有%d个客户正在运行!\r\n",skt,g_ThreadNum);
    ShowContent((LPCTSTR)cs);
    }UINT SvrThread(LPVOID pParam)
    {
    g_ThreadNum = 0; //主侦听线程不算
    CString cs;
    cs.Format("服务器启动.......\r\n");
    ShowContent((LPCTSTR)cs); ESocketServer svr;
    svr.NewExchange = HandleNew;
    svr.InitSvr(8888);
    return svr.RunLoop();
    }
    然后在需要启动服务器的地方启动SvrThread线程就可以了
      

  7.   

    There are many good examples about "Http Server with Multi-thread capability" on website codegugu.