2016-08-30 78 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