2013-07-18 66 views
0

我在C的一個問題,我沒有得到解決......通過UDP發送非文本文件不起作用

我寫了一個服務器端和一個在C客戶端應用程序

服務器應用程序讀取一個文件並將其分割成1024字節的塊,以便通過UDP將其發送到客戶端應用程序。

客戶端應用程序獲取這些塊,創建並寫入新文件。

如果輸入文件是應用程序正在工作的文本文件。

對於我目前正在研究的項目,我需要發送媒體文件(.mp3,.mp4,.ogg等)(是的,我需要爲此使用UDP)。如果我想發送像這樣的文件,它不起作用。

我的問題:

  • 當我通過UDP套接字獲取數據,我得到1024個數據的每一次我收到一個消息 - 除了與上次包。應用程序將它通過UDP獲取的數據保存在char數組中。爲了獲得消息的長度,我檢查數組中的空字段。 (我嘗試了不同的方式,但沒有奏效......)對文本文件適用,但不適用於媒體文件。我怎樣才能做得更好? (大概不僅inefficent但糟糕的編碼風格,太...)

    int l = 0; 
    n = 0; 
    for(l = 0; l<sizeof(buffer) ;l++){ 
    
        if(buffer[l] != NULL){ 
         n++; 
        } 
    
    } 
    
  • 什麼我必須做正確發送非文本數據?有通過UDP發送文件的更好的解決方案嗎?有人有一些建議嗎?

這裏是我對C-文件:

server.c

#include<arpa/inet.h> 
#include<netinet/in.h> 
#include<stdio.h> 
#include<unistd.h> 
#include<sys/types.h> 
#include<sys/socket.h> 
#include<stdlib.h> 
#include<string.h> 

#define PORT 9333 
#define SERVER_IP "127.0.0.1" 
#define BUFFER_SIZE 1024 

FILE *input; 
FILE *checkfile; 
int n; 
int count = 0; 

struct sockaddr_in remote; 
int s;    


int main(){ 

unsigned char buffer[BUFFER_SIZE]; 
    char check[100]; 

printf("Press ENTER to send file!\n"); 
fgets(check, 100, stdin); 


input = fopen("input.txt", "r"); 
checkfile = fopen("checkfile.txt", "w"); 

if(input){ 

    if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){ 
     fprintf(stderr, "Error getting a socket! \n"); 
     exit(-1); 
    } 

    memset((char *) &remote, 0, sizeof(remote)); 

    remote.sin_family = AF_INET; 
    remote.sin_port = htons(PORT); 


    if(inet_aton(SERVER_IP, &remote.sin_addr) == 0){ 
     fprintf(stderr, "maybe no valid adress\n"); 
     exit(1); 
    } 

    while(!feof(input)){ 
     n = fread(buffer, 1, BUFFER_SIZE, input); 
     count += n; 
     printf("n = %d\n", n); 

     if(sendto(s, buffer, n, 0, &remote, sizeof(remote)) == -1){ 
      fprintf(stderr, "error while sending data!\n"); 
      exit(-1); 
     } 
     fwrite(buffer, 1, n, checkfile); 
    } 
    printf("%d bytes sent. \n", count); 

}else{ 
    printf("error while opening input file!"); 
} 
printf("File sent!!\n"); 

close(s); 
fclose(input); 

return 0; 
} 

client.c:

#include<arpa/inet.h> 
#include<netinet/in.h> 
#include<stdio.h> 
#include<unistd.h> 
#include<sys/types.h> 
#include<sys/socket.h> 
#include<stdlib.h> 
#include<string.h> 

#define PORT 9333 
#define BUFFER_SIZE 1024 

int n; 
FILE *output; 

struct sockaddr_in local, remote; 
int len_remote = sizeof(remote); 
int s; 
int count = 0; 

int main(){ 

char buffer[BUFFER_SIZE]; 
output = fopen("output.txt", "w"); 

if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){ 
    fprintf(stderr, "Error getting a socket!\n"); 
    exit(-1); 
} 

memset((char *) &remote, 0, sizeof(remote)); 
memset((char *) &local, 0, sizeof(remote)); 

local.sin_family = AF_INET; 
local.sin_port = htons(PORT); 
local.sin_addr.s_addr = htonl(INADDR_ANY); 

if(bind(s, &local, sizeof(local)) == -1){ 
    fprintf(stderr, "Cannot connect to service!\n"); 
    exit(-1); 
} 

int flag = 1; 

while(flag == 1){ 

    memset(buffer, '\0', BUFFER_SIZE); 

    if(recvfrom(s, buffer, BUFFER_SIZE, 0, &remote, &len_remote) == -1){ 
     fprintf(stderr, "fail while receiving data! \n"); 
     exit(-1); 
    } 

    int l = 0; 
    n = 0; 
    for(l = 0; l<sizeof(buffer) ;l++){ 

     if(buffer[l] != NULL){ 
      n++; 
     } 

    } 

    count += n; 
    printf("n = %d\n", n); 

    fwrite(buffer, 1, n, output); 

    if(n<1024){ 
     flag = 0; 
    } 

} 
printf("Got the file!\n"); 

close(s); 
fclose(output); 
return 0; 

} 

如果有人對我一些幫助/建議,那太好了。

最好的問候,

菲爾

+0

創建2個數據文件,演示問題(一個工作,一個不),並將內容作爲每個十六進制轉儲發送 –

+0

在發送實際文件發送文件屬性之前,請等待 –

+0

告訴我您的操作系統?另請檢查文件大小(客戶端/服務器)兩側。如果Size相同,那麼在發送端更改傳輸文件的權限和屬性相同 –

回答

0

從client.c:

int nbrecv = 0;  
while(flag == 1){ 

    memset(buffer, '\0', BUFFER_SIZE); 

    if((nbrecv = recvfrom(s, buffer, BUFFER_SIZE, 0, &remote, &len_remote)) == -1){ 
     fprintf(stderr, "fail while receiving data! \n"); 
     exit(-1); 
    } 

    count += nbrecv; 
    printf("n = %d\n", nbrecv); 

    fwrite(buffer, 1, nbrecv, output); 

    if(nbrecv<1024){ 
     flag = 0; 
    } 

} 

recvfrom()將返回接收的字節數,使用它。

請注意,UDP沒有任何保證(數據包未被重新排序,或其他)。如果使用UDP,則可能需要創建一個基本協議,該協議將包含一些信息(數據包的編號,數據包中的字節數等)。

+0

非常感謝,解決了這個問題。 –