发送数据中的套接字问题

时间:2016-07-29 13:27:27

标签: c++ linux sockets

我在Linux上使用C ++中的套接字发送数据(10个文件,每个大约10-20 kb)。

我在服务器中的伪代码:

for(i=0;i<10;i++){
    ret = send(sockfd, filedata, filedatasize, 0);
}

ret为所有数据文件返回正确的文件大小,没有错误,但客户端只接收4-5个文件。

但是,如果我改用它:

for(i=0;i<10;i++){
    ret = send(sockfd, filedata, filedatasize, 0);
    sleep(1);
}

客户端接收所有文件,而不是错误!

有什么问题?

我尝试调整SO_RCVBUFSO_SNDBUF,但没有更改。

编辑:(完整的代码有20万行要粘贴!)

这是服务器代码:

int Socket::sendMsg(char * data, unsigned int uiSize)
{
     unsigned short * us;
     int    i, iRet;


      us = (unsigned short *)(m_pSendBuffer);
      *us = (unsigned short)(uiSize + 2);

      memcpy((char *)m_pSendBuffer + 2, data, uiSize);
      iRet = isend(m_pSendBuffer, uiSize + 2);
      if (iRet<0) {
           return SOCKET_ERROR;
      }
      return iRet;
}
int Socket::isend(char * data, int size)
{
    int  outlen, ret;

    outlen= 0;
    while (outlen< size) {
        ret= send(sockfd, (data+ outlen), size - outlen, 0);

        if (ret< 0) {
            return -1;
        }
        else outlen+= ret;
    }
    return outlen;
}

以下是客户端代码:

void XSocket::onRead()
{
    int iRet;
    unsigned short  * usp;
    unsigned int uiReadSize;

    while (1) {
        iRet = recv(m_Sock, (char *)m_pRecvBuffer, 2, 0);
        uiReadSize = 0;


        usp = (unsigned short *)(m_pRecvBuffer);
        uiReadSize = (int)(*usp - 2);

        iRet = recv(m_Sock, (char *)(m_pRecvBuffer + 2), uiReadSize, 0);

        if (iRet < 0) {
            //return error              
        }
        else if (iRet == 0) {
            //disconnect
        }
        //PROCCESS MSG
    }
}

2 个答案:

答案 0 :(得分:1)

在客户端:

  1. 您在第一次recv()呼叫时没有进行任何错误处理,如果服务器正常断开连接,您的第二次recv()呼叫不会中断循环。

  2. 您没有循环读取每个数据缓冲区,就像您在服务器端循环发送它们一样。发送的字节数和接收的字节数之间没有1对1的关系。如果您希望X字节到达,请继续阅读,直到您实际收到这么多字节为止。

  3. 鉴于这些错误,无法保证您的客户端实际上正确地接收了所有数据。

    尝试更像这样的事情:

    void XSocket::onRead()
    {
        int iRet;
        unsigned short  * usp;
        unsigned int uiReadSize;
    
        while (1) {
            iRet = irecv((char *)m_pRecvBuffer, 2);
            if (iRet<= 0) {
                break;
            }
    
            usp = (unsigned short *)(m_pRecvBuffer);
            uiReadSize = (int)(*usp - 2);
    
            iRet = irecv((char *)(m_pRecvBuffer + 2), uiReadSize);
            if (iRet<= 0) {
                break;
            }
    
            //PROCCESS MSG
        }
    }
    
    int XSocket::irecv(char * data, int size)
    {
        int  inlen, ret;
    
        inlen= 0;
        while (inlen< size) {
            ret= recv(m_Sock, (data+ inlen), size - inlen, 0);
    
            if (ret< 0) {
                return -1;
            }
            else if (ret== 0) {
                return 0;
            }
            else {
                inlen+= ret;
            }
        }
        return inlen;
    }
    

答案 1 :(得分:0)

我解决了这个问题!!,我将epoll从边缘触发改为水平触发,并解决了!