套接字 - 在c中发送一个大字符串

Yos*_*lon 1 c sockets

我试图理解为什么我的函数dosnt发送所有字符串(它只从365568发送53576元素:这是我在客户端使用的函数:

#define DATASIZEBUFFER 4000// 365568
void DieWithError(char *errorMessage);/* Error handling function */


void TcpClient ( char *servIP , unsigned short echoServPort , Hash_t *HashData)//(int argc, char *argv[])
{
int sock;                           //Socket descriptor 
struct sockaddr_in ServAddr;    //Echo server address            
int bytesRcvd, totalBytesRcvd;      //Bytes read in single recv()
                                    //and total bytes read      

// Create a reliable, stream socket using TCP 
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    DieWithError(" socket () failed") ;

// Construct the server address structure 
memset(&ServAddr, 0, sizeof(ServAddr));  /* Zero out structure */
ServAddr.sin_family = AF_INET;               /* Internet address family */
ServAddr.sin_addr.s_addr = inet_addr(servIP);/* Server IP address */
ServAddr.sin_port = htons(echoServPort);    /* Server port */

// Establish the connection to the server 
if (connect(sock, (struct sockaddr *) &ServAddr, sizeof(ServAddr)) < 0)
    DieWithError(" connect () failed") ;
for (;;)
{
// Send the string to the server //

    if (send(sock, HashData->array , HashData->elementNumber, 0) != HashData->elementNumber)
    {
        printf ("Bytes Nedded to recived: %ld\nAnd (DATASIZEBUFFER) is %d\n", HashData->elementNumber , DATASIZEBUFFER);
        DieWithError("send() sent a different number of bytes than expected");
    }
}
Run Code Online (Sandbox Code Playgroud)

Aru*_*run 7

send()不保证它会发送所有数据.

从发送手册页:

   On success, these calls return the number of bytes sent.  On error,
   -1 is returned, and errno is set appropriately.
Run Code Online (Sandbox Code Playgroud)

您可以编写循环send()并多次调用它,直到发送所有数据(或返回错误).它可能类似于以下内容(请根据您的需要进行修改):

size_t 
Send(int sockfd, const void *buf, size_t len, int flag) {
  size_t sent_total = 0;
  for (int sent_now = 0; sent_total != len; sent_total += sent_now) {
    sent_now = send(sockfd, buf + sent_total, len - sent_total, flag);
    if (sent_now == -1) break;
  }
  if (sent_total != len) {
    LOG("send requested = %zu, sent = %zu", len, sent_total);
  }
  return sent_total;
}
Run Code Online (Sandbox Code Playgroud)

更新以解决@Myst的评论:

虽然问题没有明确提到它,但我认为使用的套接字是阻塞的,因为没有fcntl调用.考虑到这一点,send()手册页中的以下内容解释了这种情况:

   When the message does not fit into the send buffer of the socket,
   send() normally blocks, unless the socket has been placed in
   nonblocking I/O mode. 

   In nonblocking mode it would fail with the
   error EAGAIN or EWOULDBLOCK in this case.  The select(2) call may be
   used to determine when it is possible to send more data.
Run Code Online (Sandbox Code Playgroud)

对于非阻塞套接字,设计需要不同,并且超出了本讨论的范围.

  • @DavideVisentin,这就是为什么你的答案中的代码不起作用的原因.您将在发送数据之前退出循环.要么实现轮询或循环,直到返回"-1"并且`errno`既不是'EAGAIN`也不是'EWOULDBLOCK`. (2认同)