2012-05-20 180 views
0

嗨,我寫了一個服務器應用程序,它接受通常是文件名的客戶端的名稱。它打開文件,將內容讀入緩衝區,然後使用send()通過以太網傳輸緩衝區。但問題出現在所有字節都沒有被成功接收的客戶端。我只收到我發送的一部分內容。如何使用套接字apis發送和接收字節?

供您參考,下面是服務器端的代碼片段:

服務器

fp = fopen(filename,"r+"); 
     strcpy(str,""); 
     fseek(fp, 0L, SEEK_END); 
     size = ftell(fp); 
     fseek(fp, 0L, SEEK_SET); 
     fread(str, size, 1,fp); 
     fclose(fp); 
     printf("Size of the file is : %d\n",size); 
     sprintf(filename, "%d", size); 
     n = send(nsd, filename, strlen(filename), 0); 

while(size > 0){ 
      n = send(nsd, str, strlen(str), 0); 
      printf("%d bytes sent successfully\n",n);   
      if(n == 0) break; 
      sentbytes = sentbytes + n; 
      size = size - sentbytes; 
     } 

請幫我寫客戶端app.I我目前困惑如何去寫它。我是否將recv()部分放在while(1)循環中,以便客戶端繼續運行,直到所有字節都已成功接收爲止?

+0

你用什麼樣的插座?它是一個UDP套接字?如果是這種情況,你應該迎合丟包和轉發...或者,你可以去TCP ... – user1055604

+0

這是我使用的TCP套接字... – phoenix

回答

3

EDITED
對於初學者來說,你可以在同一時間既塊和read from the filewrite to the socket
因爲您正在通過TCP傳輸數據,所以請記住,數據作爲流可靠傳輸,而不是作爲消息傳輸。因此,除了訂單外,不要對數據如何被收回做出假設。

這裏是如何可以寫成:

open socket 
open file 
size_of_file = read_file_size(file); 
send(socket, &size_of_file, sizeof(int), ...) 
while (all is written) 
    read fixed chunk from file 
    write as much was read to the socket 
cleanup // close file, socket 

至於recv的一部分,我認爲這是最好的,你發送的文件大小比爲整數,並保持在讀一while循環,直到您已經收到了從服務器發送的儘可能多的字節數。

是這樣的:

recv(socket, &size_of_msg, sizeof(int), ...) 
while(all is read) 
    read fixed chunk from the socket 
cleanup 
2

「我應該在一個while(1)循環中放置recv()部分,以便客戶端繼續運行,直到所有字節都被成功接收爲止?」

就是這樣的。永遠不要假定recv()調用獲得了所有發送的內容 - tcp/ip將消息分解爲較低級別的數據包,recv()將在讀取任何點上實際接收到的任何數據量後返回。您不必直接擔心,除非您確實需要使用某種協議來指示消息的長度,因此接收方知道要讀多少,然後例如:

char buffer[4096]; 
int msgsz = 600, // see below 
    sofar = 0, 
    cur; 

while (sofar < msgsz) { 
    cur = recv (
     socket_fd, 
     &buffer[sofar], 
     msgsz - sofar, 
     0 
    ); 
    if (cur == -1) { 
     // error 
     break; 
    } else if (cur == 0) { 
     // disconnected 
     break; 
    } 
    sofar += cur; 
} 

WRT msgsz,你可以將它包含在固定長度的頭文件中,這是首先讀取的。一個簡單的版本可能只是4個字節,包含一個uint32_t,即一個int長度。您也可以使用以空字符結尾的字符串和一個數字,但這意味着直到找到'\0'

2

使用strlen似乎並不合適。你已經讀過這個文件,你知道它有多長,爲什麼strlen?要麼你會得到相同的結果(所以它是多餘的),否則你會得到其他東西(所以這是一個錯誤)。

3

那麼我看到至少有一些問題,你通過套接字發送消息的方式。

從FREAD的手冊頁第一:

The function fread() reads nmemb elements of data, each size bytes 
    long, from the stream pointed to by stream, storing them at the loca- 
    tion given by ptr. 

和你正在嘗試是這樣的:

fread(str, size, 1,fp); 

我假設你的意思是

fread(str, 1,size,fp); 

雖然shold不是問題。

但問題就出在這裏:

n = send(nsd, str, strlen(str), 0); 
     printf("%d bytes sent successfully\n",n);   
     if(n == 0) break; 
     sentbytes = sentbytes + n; 
     size = size - sentbytes; 

雖然你會減少「大小」由字節數減少發送成功,你在哪裏延伸STR指向新緩衝區的位置,其中的數據將被髮送。這將只會重複發送緩衝區的初始字節。

 str += n; //Assuming str is char* 

將解決您的問題。

相關問題