2013-06-13 88 views
1

我正在为TR-069服务器编写CWMP客户端。我立足于这个话题我的客户的代码(另外还有主题中源代码的链接)recv()错误C/C++套接字编程

CWMP CPE (Client) implementation

我曾经遇到过一个奇怪的问题是的recv()不读取发送的数据!我检查了我发送的数据,这是正确的。我已经在服务器端安装了一个Wireshark,它捕获了发送相同数据客户端的数据包。我正在挖掘TR-069 ACS源代码,并试图将侦听套接字模式更改为NON_BLOCK - 没用。

插槽定义来源:

int make_socket(unsigned int port) 
{ 
    int sock; 
    struct sockaddr_in name; 
    sock = socket(PF_INET, SOCK_STREAM, 0); 
    if (sock < 0) 
    { 
    logtr("ACS Server:", "Can not create socket", ERROR, conferr); 
    exit(EXIT_FAILURE); 
    } 
    name.sin_family = AF_INET; 
    name.sin_port = htons(port); 
    name.sin_addr.s_addr = htonl(INADDR_ANY); 
    if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) 
    { 
    // perror ("bind"); 
    logtr("ACS Server:", "Can not bind ", ERROR, conferr); 
    exit(EXIT_FAILURE); 
    } 
    return sock; 
} 

处理:

void connection(int sock) 
{ 
    if (listen(sock, 10) < 0) 
    { 
    //perror ("listen"); 
    logtr("ACS Server:", "Can not listen socket", ERROR, conferr); 
    exit(EXIT_FAILURE); 
    } 

    FD_ZERO(&active_fd_set); 
    FD_SET(sock, &active_fd_set); 

    // int status = 3; 

    while (1) 
    { 
    timeout.tv_sec = 10; 
    timeout.tv_usec = 0; 

    read_fd_set = active_fd_set; 
    if (select(FD_SETSIZE + 1, &read_fd_set, NULL, NULL, &timeout) < 0) 
    { 
     //perror ("Select"); 
     logtr("ACS Server:", "Can not select socket", ERROR, conferr); 
     exit(EXIT_FAILURE); 
    } 
    for (i = 0; i <= FD_SETSIZE; ++i) 
     if (FD_ISSET(i, &read_fd_set)) 
     { 
     if (i == sock) 
     { 
      size = sizeof(clientname); 
      newfd1 = accept(sock, (struct sockaddr *) &clientname, &size); 
      if (newfd1 < 0) 
      { 
      //perror ("accept"); 
      logtr("ACS Server:", "Can not accept socket", ERROR, conferr); 
      exit(EXIT_FAILURE); 
      } 
      /* 
      fprintf (stderr,"Server: connect from host %s, port %i\n", 
      (char*)inet_ntoa(clientname.sin_addr), 
      ntohs(clientname.sin_port)); 
      */ 
      char info[128]; 
      sprintf(info, "Server: connect from host %s, port %i\n", 
       (char*) inet_ntoa(clientname.sin_addr), 
       ntohs(clientname.sin_port)); 
      trace(info); 

      FD_SET(newfd1, &active_fd_set); 

      memset(fileCBuff[i].fileContBuff, 0, 
       sizeof(fileCBuff[i].fileContBuff)); 
      out_get_param_value0 = 0; 
      out_get_param_value1 = 0; 
      c_reboot = 0; 
      c_download = 0; 
      noSqlError = 0; 

     } 
     else 
     { 
      send_recive_socket(i); 
     } 
     } 
    } 
} 

最后它失败:

void send_recive_socket(int i) 
{ 
    if(read_from_client(i) < 0) 
    { 
    CLOSECONNECTION: 
    close(i); 
    FD_CLR (i,&active_fd_set); 
//printf("\nClose connection ......\n");\ 
    } 
    else 
    { 
    ... 

int read_from_client(int fileDesc) 
{ 
    int nbytes; 
    memset(buffer,0,READ_MSG_SIZE); 
    nbytes = recv(fileDesc, buffer, READ_MSG_SIZE,0);//reade data from client 
    if(nbytes <= 0) 
    { 
    logtr("ACS Server:","Wait Data from TR069 Client ", ERROR, conferr); 
    // printf("\nNo data from client"); 
    // perror ("Read ..."); 
    return -1; 
    } 
    else 
    { 
    ... 

我想这是因为每当我阻止客户执行的地方日志收到

ACS Server: Wait Data from TR069 Client ERROR servHelper.c read_from_client 

预先感谢您。

+2

你在这里展示设计每当客户端登录错误的代码无论出于何种原因断开。您确定以正确的格式发送数据,并且服务器不仅仅处于等待更多数据的状态,因为您已经发送的数据不正确?另外,如果没有处理recv/send等事实,则将套接字更改为非阻塞听起来像是一个坏主意,因此可能会因EWOULDBLOCK而失败。 – nos

+0

你的代码如何处理'recv()'返回一个值'> 0'和' alk

回答

2

recv可能会返回-1errno设置为EINTR当信号到达时。这是暂时的失败,并不表示您的套接字连接有任何问题。您可能想要忽略此错误并尝试再次调用recv。要做到这一点在Linux上最简单的方法是使用TEMP_FAILURE_RETRY

nbytes = TEMP_FAILURE_RETRY(recv(fileDesc, buffer, READ_MSG_SIZE,0)); 

这将调用recv,直到它返回其他的东西比nbytes==-1 && errno==EINTR