我封装了套接字,执行获取网页源码的功能我采取的是tcp协议,阻塞模式的。这个是我自己定义初始化socket以及连接主机、端口的函数(没问题)bInitSocket(CString pHost,//主机,域名
            int nPort)//端口号
{
    //...
    //连接服务器
    if (connect(m_Socket, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
    {
        MessageBox(NULL, "Connect Error!", "Error", 0);
        CloseSocket();
        return FALSE;
    }
    //...
}
这个是我自己封装的发送包的方法(没问题)nPostPackage(const CString strPockage)
{
    //....
    //发送数据
    nSend = send(m_Socket, strNewPockage.GetBuffer(0), strNewPockage.GetLength(), 0);
    //...
}
这个是我自己封装的在调用nPostPackage方法后执行接收数据的方法(没问题)nGetData()
{
        while (nRet > 0)
{
                //...
// 接收返回数据包
nRet = recv(m_Socket, (LPSTR)arryRecv, sizeof(arryRecv), 0);
                //...
        }
{}
这个是我自己封装的关闭套接字的方法(没问题)CloseSocket()
{
        try
{
shutdown(m_Socket, 0X02);
closesocket(m_Socket);
WSACleanup();
}
catch (...)
{
MessageBox(NULL, "Close socket fail", "Error", 0);
}
}**************************
接下来就是我的问题。
我循环(当循环第一次就能nPostPackage和nGetData成功,但是循环第二次的时候就会nGetData返回0个数据){
    nPostPackage(const CString strPockage);//发送数据包后
    nGetData();//接收数据
}
然后我修改成(这个就能成功执行完所有我的循环){
    bInitSocket(CString pHost,//主机,域名
            int nPort);//端口号//初始化并且连接服务器
    nPostPackage(const CString strPockage);//发送数据包后
    nGetData();//接收数据
    CloseSocket();//关闭套接字
}
问题一:为什么修改成这样之后才能成功?
问题二:因为每循环一次都需要连接和关闭套接字,这样性能急剧下降,有没有什么好的办法可以解决此处的性能问题?我只想使用同一个套接字对象,不想创建多个套接字对象。谢谢。

解决方案 »

  1.   

    没看到你的循环,不过,TCP连接是不需要每次都关闭的.
      

  2.   

    你好,当我没关闭再执行一次send recv后,recv的数据是空的,是不是send前做什么操作呢?我的数据包是正确的,网络也是好的。谢谢。
      

  3.   

    你不知道HTTP协议是短连接么?
    每次操作以后服务器close了这个连接
      

  4.   

    貌似没有releasebuff(),我以前也碰到过这个问题,我是因为发送和接受缓冲区大小设置不一样导致的。
      

  5.   

    回复于:2012-10-13 15:23:35没看到你的循环,不过,TCP连接是不需要每次都关闭的. 
      

  6.   


    close以后宣告这个连接失效
      

  7.   

    那这样的话是不是每次send和recv后都需要再绑定服务器和端口呢?不用这么麻烦吧。
      

  8.   

    没看到楼主的具体调用代码。不知道是不是这个原因呢
    send(),send(),recv(),recv()还是send(),recv(),send(),recv()?
    如果是前者,可能第一次recv()就把两次send的都接收的。如果不是这个问题,可以查看一下,第一次recv是不是send的长度。第二次send是否成功;成功,send的长度。问题可以一步一步分析
      

  9.   

    你好,我是执行你所说的第二种。recv肯定不会等于send的长度啦,send的是数据包,recv得到的数据肯定不是原先发送过去的数据包。就是在第二次send和recv这里接收不到数据,事实上这里send和recv我检测返回参数都是没问题的啊。
      

  10.   

    第一次nGetData()之后,该函数退出没?修改为nGetData()
    {
            while (true)
        {
                    //...
            // 接收返回数据包
            int nRet = recv(m_Socket, (LPSTR)arryRecv, sizeof(arryRecv), 0);
                    //...
            if(nRet  > 0)
            {
             //todo
            }
            else()
            {}
          }
    {}
      

  11.   

    另外一个问题,一般send之前,会在包头添加四个字节,用来表示本次发送包的大小;
    同理,recv之后,包头前四个字节可以表示为int,与recv的长度进行比较。
      

  12.   

    你好,第一次nGetData()之后该函数已经退出了,然后为什么要在while里面sleep?我用的是阻塞模式的,只有接收数据完毕后才能返回的。
      

  13.   

    比如你某次发送了1000个字节,在recv的时候,可能第一次recv;100,第二次为0,第三次500.第三次0,第四次400
      

  14.   

    你好,我可确定我是send成功(服务器能接收到我的数据),nGetData(){recv()}成功,得到服务器返回的数据时完全的;然后我才再次send和获取数据的。不存在接收数据多少的问题,因为我已经能确定我第一次send完全和recv完全了。在recv完全之后我才执行第二次send的。
      

  15.   


    要知道,一个连接,除了你自己close以外, 服务器也是可以close的。
    你返回0,说明就是服务器已经close了啊,所以你必须重新连接。至于为何服务器会主动close, 你没有说你连的是什么服务器,说以不好说。
    如果你连的是HTTP网站,正如cl_gamer所说,HTTP服务器在给你返回数据后,就会close连接。
      

  16.   

    你好,我连接的是web 服务器,是http的。每次都要从新连接的话这样岂不是很耗资源和事件,如果我并发的话,这样岂不是会失败。?谢谢指导。
      

  17.   

    用wireshark抓包来看看,是不是服务端有[FIN,ACK]包发过来,有的话,表明服务端释放了连接.