简体   繁体   English

socket recv() 没有接收到数据

[英]socket recv() doesn't receive data

I have a server daemon listening on a TCP unix domain/local socket.我有一个服务器守护进程监听 TCP unix 域/本地套接字。 Multiple clients running on the same machine connect to it.在同一台机器上运行的多个客户端连接到它。 The daemon is also bound to a UDP Inte.net socket.该守护进程还绑定到 UDP Inte.net 套接字。 Whenever the daemon receives any data from one of the local clients, it sends the same data to all the connected clients except the sending client.每当守护程序从其中一个本地客户端接收到任何数据时,它都会将相同的数据发送到除发送客户端之外的所有连接的客户端。 If the daemon receives data on the UDP inte.net socket, it needs to send that data to all the local connected clients.如果守护进程在 UDP inte.net 套接字上接收到数据,它需要将该数据发送到所有本地连接的客户端。 The sending/receiving of data works perfectly when the daemon receives data on the local socket.当守护程序在本地套接字上接收数据时,数据的发送/接收工作完美。 However, the clients do not receive any data when the server sends them data received on the UDP inte.net socket.但是,当服务器向客户端发送在 UDP inte.net 套接字上接收到的数据时,客户端不会收到任何数据。 The clients receive that inte.net data either after the server daemon is exited and the connection is closed, or, when any of the clients sends data locally to the server.在服务器守护程序退出并关闭连接后,或者在任何客户端将数据本地发送到服务器时,客户端会收到该 inte.net 数据。 The inte.net data is received by the clients along with the local data. inte.net 数据与本地数据一起由客户端接收。 I have set both local and .net sockets as blocking using fcntl() .我已使用fcntl()将本地和 .net sockets 设置为阻止。 Here is the daemon code that I have (I have removed all the unnecessary code):这是我拥有的守护程序代码(我删除了所有不必要的代码):

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);
      }
    }
  } 
}

Here is the client code that I have:这是我的客户端代码:

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));
  }
}

The goal is to have the clients receive data immediately that the daemon sends them (the data which the daemon receives on its .net socket).目标是让客户端立即接收守护程序发送给它们的数据(守护程序在其 .net 套接字上接收的数据)。

EDIT: I have figured that when the daemon sends the data, the select() on the client side returns that the socket is readable, but recv() is blocking, that's the reason I'm not getting data on the client side.编辑:我发现当守护进程发送数据时,客户端的 select() 返回套接字可读,但 recv() 正在阻塞,这就是我没有在客户端获取数据的原因。 Any suggestions on how to fix this?对于如何解决这个问题,有任何的建议吗?

Here's the send() calls from your code, extracted and aligned:这是从您的代码中提取和对齐的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);

I see some inconsistencies here.我在这里看到了一些不一致之处。 Sometimes you call strlen() , sometimes strnlen() , and sometimes strlen() with two arguments (I don't even know what that's going to do).有时你调用strlen() ,有时调用strnlen() ,有时调用 strlen( strlen()两个 arguments (我什至不知道那会做什么)。

The problem you're seeing may be related to the fact that you're not sending any information on the socket that shows where the boundaries between messages are.您看到的问题可能与您没有在显示消息之间边界的套接字上发送任何信息这一事实有关。 Over a stream socket, message boundaries are not preserved and you should take care to include appropriate framing information in your protocol so that the receiver can extract the individual messages.在 stream 套接字上,不会保留消息边界,您应该注意在协议中包含适当的帧信息,以便接收方可以提取各个消息。 You cannot rely on exactly the same number of bytes coming through a recv() call as there was in a send() call.您不能依赖于通过recv()调用的字节数与send()调用中的字节数完全相同。 You will get the same total number of bytes in the same order (that's the point of a stream socket), but the messages might get consolidated or split up and you have no control over that.您将以相同的顺序获得相同的字节总数(这是 stream 套接字的重点),但消息可能会合并或拆分,您无法控制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM