首页 文章

socket recv()不接收数据

提问于
浏览
1

我有一个服务器守护进程侦听TCP unix域/本地套接字 . 在同一台计算机上运行的多个客户端连接到它 . 守护程序也绑定到UDP Internet套接字 . 只要守护程序从其中一个本地客户端接收任何数据,它就会将相同的数据发送到除发送客户端之外的所有连接的客户端 . 如果守护程序在UDP Internet套接字上接收数据,则需要将该数据发送到所有本地连接的客户端 . 当守护进程在本地套接字上接收数据时,数据的发送/接收工作正常 . 但是,当服务器向UDP Internet套接字发送数据时,客户端不会收到任何数据 . 客户端在退出服务器守护程序并关闭连接后,或者当任何客户端在本地向服务器发送数据时,都会收到该Internet数据 . 客户端连同本地数据一起接收互联网数据 . 我已使用 fcntl() 将local和inet套接字设置为阻塞 . 这是我的守护进程代码(我删除了所有不必要的代码):

while(1)
{
  FD_SET(sockfd, &read_fds);
  FD_SET(inet_sock, &read_fds);
  for (i = 0; i < nclients; i++)
  {
    FD_SET(clients[i], &read_fds);
  }

  select(maxfd + 1, &read_fds, &write_fds, &except_fds, NULL);

  /* Check for events on inet sock */
  if (FD_ISSET(inet_sock, &read_fds))
  {
    /* Read from inet sock */
    socklen = sizeof(dest_sin);
    rval = recvfrom(inet_sock, buf, BUFLEN-1, MSG_DONTWAIT,
                    (struct sockaddr *) &dest_sin, &socklen);        
    buf[rval]=0;
    fprintf(stderr, "Received: %d (%d) bytes containing %s", rval, strlen(buf), buf);

    /* Send the message to every other client */
    for(j=0; j < nclients; j++)
    {
      send(clients[j], buf, strlen(buf), MSG_DONTWAIT);
    }
  }

  /* A read event on the local socket is a new connection */
  if (FD_ISSET(sockfd, &read_fds))
  {
    socklen = sizeof(dest_sun);
    /* Accept the new connection */
    rval = accept(sockfd, (struct sockaddr *) &dest_sun, &socklen);

    /* Add client to list of clients */
    clients[nclients++] = rval;
    if (rval > maxfd) maxfd = rval;
    snprintf(s, BUFLEN, "You are client %d [%d]. You are now connected.\n\0",
        nclients, rval);
    send(rval, s, strnlen(s, BUFLEN), MSG_DONTWAIT);
  }

  /* Check for events from each client */
  for (i = 0; i < nclients; i++)
  {
    fprintf(stderr,"Checking client %d [%d] for read indicator.\n",i, clients[i]);

    /* Client read events */
    if (FD_ISSET(clients[i], &read_fds))
    {
      fprintf(stderr, "Client %d [%d] marked for read.\n", i, clients[i]);

      /* Read from client */
      rval=recv(clients[i], buf, BUFLEN-1, MSG_DONTWAIT);

      buf[rval]=0;
      fprintf(stderr, "Received: %d (%d) bytes containing %s", rval, strlen(buf), buf);

      /* Send the message to every other client */
      for(j=0; j < nclients; j++)
      {
        /* Skip the sender */
        if (j == i) continue;
        /* Send the message */
        send(clients[j], s, strlen(s, BUFLEN), MSG_DONTWAIT);
      }
    }
  } 
}

这是我的客户端代码:

while(1)
{
  FD_SET(fileno(stdin), &read_fds);
  FD_SET(sockfd, &read_fds);
  select(fileno(stdin) > sockfd ? fileno(stdin)+1 : sockfd+1,
&read_fds, &write_fds, &except_fds, NULL);

  if (FD_ISSET(sockfd, &read_fds))
  {
    /* Read from socket and display to user */
    mlen = recv(sockfd, (void *)buf, BUFLEN-1, MSG_DONTWAIT);
    buf[mlen]=0;
    printf("Received %d bytes: %s", mlen, buf);
  }

  if (FD_ISSET(fileno(stdin), &read_fds))
  {
    fgets(buf, BUFLEN, stdin);
    fprintf(stderr, "Sent %d octets to server.", 
    send(sockfd, (void *)buf, (size_t) strnlen(buf, BUFLEN), 0));
  }
}

目标是让客户端立即接收守护程序发送的数据(守护程序在其inet套接字上接收的数据) .

编辑:我认为当守护进程发送数据时,客户端的select()返回套接字是可读的,但recv()是阻塞的,这就是我没有在客户端获取数据的原因 . 对于如何解决这个问题,有任何的建议吗?

1 回答

  • 1

    这是来自您的代码的 send() 调用,已提取并对齐:

    send(clients[j], buf, strlen(buf),        MSG_DONTWAIT);
    send(rval,       s,   strnlen(s, BUFLEN), MSG_DONTWAIT);
    send(clients[j], s,   strlen(s, BUFLEN),  MSG_DONTWAIT);
    

    我在这看到一些不一致的地方 . 有时你用两个参数调用 strlen() ,有时是 strnlen() ,有时是 strlen() (我不打算这样做) .

    问题是're seeing may be related to the fact that you'没有在套接字上发送任何显示消息之间边界的信息 . 在流套接字上,不保留消息边界,您应该注意在协议中包含适当的成帧信息,以便接收方可以提取单个消息 . 您不能像通过 send() 调用那样通过 recv() 调用完全相同的字节数 . 您将获得相同顺序的相同总字节数(即流套接字点),但消息可能会合并或拆分,您无法控制它 .

相关问题