2016-08-30 87 views
1

我想知道为什么我的功能dosnt从365568发送所有的字符串(其只发送53576元送一个大的字符串: 这是我使用在客户端的功能:插座 - 在C

#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"); 
    } 
} 
+0

考虑使用支持用户级缓冲区的库。我写了[我自己的图书馆](https://github.com/boazsegev/c-server-tools/blob/master/docs/libsock.md),我很乐意分享。 – Myst

回答

6

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

从发送手册页:

On success, these calls return the number of bytes sent. On error, 
    -1 is returned, and errno is set appropriately. 

您可以围绕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; 
} 

更新,以解决@神秘岛的评论:

虽然这个问题没有提到它明确,我认为使用的套接字是阻塞,因为没有拨打fcntl。考虑到这一点,从发送下列()手册页介绍了情况:

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. 

对于非阻塞插座,设计需要是不同的,是本文讨论的范围之内。

+0

你可能应该在循环中添加戳(比如'select'),否则你会烧掉CPU周期。 – Myst

+0

@Myst send()暂停执行,直到它收到一些数据(或发生错误),所以我不明白你的观点。 –

+0

@DavideVisentin ...'write'暂停执行。 'send'将立即返回值'-1',errno将被设置为'EAGAIN'或'EWOULDBLOCK' ... – Myst