2015-12-21 73 views
1

我正在編寫一個C程序,以便能夠連續地在樹莓派和Windows PC電腦之間傳輸圖像文件(從服務器樹莓派到客戶端PC )使用TCP/IP套接字,但似乎有一個錯誤發送後的第1017次,服務器退出說明分段錯誤,我的意思是當我打算髮送圖像文件到我的客戶端的循環2000次服務器退出第1017張照片。通過使用樹莓派和Windows C中的套接字發送圖像(JPG)

服務器端

#include<stdio.h> 
#include<string.h> 
#include<sys/socket.h> 
#include<arpa/inet.h> 
#include<unistd.h> 
#include<iostream> 
#include<fstream> 
#include<errno.h> 

using namespace std; 

int send_image(int socket){ 

    FILE *picture; 
    int size, read_size, stat, packet_index; 
    char send_buffer[10240], read_buffer[256]; 
    packet_index = 1; 

    picture = fopen("a.jpg", "r"); 
    printf("Getting Picture Size\n"); 

    if(picture == NULL) { 
     printf("Error Opening Image File"); 
    } 

    fseek(picture, 0, SEEK_END); 
    size = ftell(picture); 
    fseek(picture, 0, SEEK_SET); 
    printf("Total Picture size: %i\n",size); 

    //Send Picture Size 
    printf("Sending Picture Size\n"); 
    write(socket, (void *)&size, sizeof(int)); 

    //Send Picture as Byte Array 
    printf("Sending Picture as Byte Array\n"); 

    do { //Read while we get errors that are due to signals. 
     stat=read(socket, &read_buffer , 255); 
     printf("Bytes read: %i\n",stat); 
    } while (stat < 0); 

    printf("Received data in socket\n"); 
    printf("Socket data: %c\n", read_buffer); 

    while(!feof(picture)) { 
     //while(packet_index = 1){ 
     //Read from the file into our send buffer 
     read_size = fread(send_buffer, 1, sizeof(send_buffer)-1, picture); 

     //Send data through our socket 
     do{ 
      stat = write(socket, send_buffer, read_size); 
     }while (stat < 0); 

     printf("Packet Number: %i\n",packet_index); 
     printf("Packet Size Sent: %i\n",read_size);  
     printf(" \n"); 
     printf(" \n"); 

     packet_index++; 

     //Zero out our send buffer 
     bzero(send_buffer, sizeof(send_buffer)); 
    } 
} 

int main(int argc , char *argv[]) 
{ 
    int socket_desc , new_socket , c, read_size,buffer = 0; 
    struct sockaddr_in server , client; 
    char *readin; 

    //Create socket 
    socket_desc = socket(AF_INET , SOCK_STREAM , 0); 
    if (socket_desc == -1) 
    { 
     printf("Could not create socket"); 
    } 

    //Prepare the sockaddr_in structure 
    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(8000); 

    //Bind 
    if(bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) 
    { 
     puts("bind failed"); 
     return 1; 
    } 

    puts("bind done"); 

    //Listen 
    listen(socket_desc , 3); 

    //Accept and incoming connection 
    puts("Waiting for incoming connections..."); 
    c = sizeof(struct sockaddr_in); 

    if((new_socket = accept(socket_desc, (struct sockaddr *)&client,  (socklen_t*)&c))){ 
     puts("Connection accepted"); 
    } 

    fflush(stdout); 

    if (new_socket<0) 
    { 
     perror("Accept Failed"); 
     return 1; 
    } 
    while(value<2000) 
    { 
     value =value+1; 
     send_image(new_socket); 
    } 

    close(socket_desc); 
    fflush(stdout); 
    return 0; 
} 

客戶端。

#include<stdio.h> 
#include<string.h> 
#include<sys/socket.h> 
#include<arpa/inet.h> 
#include<sys/ioctl.h> 
#include<unistd.h> 
#include<iostream> 
#include<fstream> 
#include<errno.h> 

using namespace std; 

//This function is to be used once we have confirmed that an image is to be sent 
//It should read and output an image file 

int receive_image(int socket) 
{ // Start function 
    int imgc = 0 ; 

    while(imgc < 2000) 
    { 
     int buffersize = 0, recv_size = 0,size = 0, read_size, write_size, packet_index =1,stat; 

     char imagearray[10240],verify = '1'; 
     FILE *image; 
     int value = 0 ; 
     //Find the size of the image 

     value = value + 1; 

     do{ 
      stat = read(socket, &size, sizeof(int)); 
     }while(stat<0); 

     printf("size = %d" , size) ; 

     if(size>1000) 
     { 
      imgc = imgc + 1 ; 
      char buffer[] = "Got it"; 

      //Send our verification signal 
      do{ 
       stat = write(socket, &buffer, sizeof(int)); 
      }while(stat<0); 

      printf("Reply sent\n"); 
      printf(" \n"); 

      char fn[100] ; 

      sprintf(fn,"a%d.jpg",imgc); 

      image = fopen(fn, "wb"); 

      if(image == NULL) { 
       printf("Error has occurred. Image file could not be opened\n"); 
       return -1; 
      } 

      //Loop while we have not received the entire file yet 

      int need_exit = 0; 
      struct timeval timeout = {10,0}; 

      fd_set fds; 
      int buffer_fd, buffer_out; 

      while(recv_size < size) { 
       //while(packet_index < 2){ 
       FD_ZERO(&fds); 
       FD_SET(socket,&fds); 

       buffer_fd = select(FD_SETSIZE,&fds,NULL,NULL,&timeout); 
       if (buffer_fd < 0) 
        printf("error: bad file descriptor set.\n"); 

       if (buffer_fd == 0) 
        printf("error: buffer read timeout expired.\n"); 

       if (buffer_fd > 0) 
       { 
        do{ 
         read_size = read(socket,imagearray, 10240); 
        }while(read_size <0); 

        printf("Packet number received: %i\n",packet_index); 
        printf("Packet size: %i\n",read_size); 

        //Write the currently read data into our image file 
        write_size = fwrite(imagearray,1,read_size, image); 
        printf("Written image size: %i\n",write_size); 

        if(read_size !=write_size) { 
         printf("error in read write\n"); 
        } 

        //Increment the total number of bytes read 
        recv_size += read_size; 
        packet_index++; 
        printf("Total received image size: %i\n",recv_size); 
        printf(" \n"); 
        printf(" \n"); 
       } 
      } 

      fclose(image); 
      printf("Image successfully Received!\n"); 
     } 

    }  
    return 1; 
} 

int main(int argc , char *argv[]) 
{ 
    int socket_desc; 
    struct sockaddr_in server; 
    char *parray; 


    //Create socket 
    socket_desc = socket(AF_INET , SOCK_STREAM , 0); 

    if (socket_desc == -1) { 
     printf("Could not create socket"); 
    } 

    memset(&server,0,sizeof(server)); 
    server.sin_addr.s_addr = inet_addr("192.168.137.137"); 
    server.sin_family = AF_INET; 
    server.sin_port = htons(8000); 

    //Connect to remote server 
    if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0)  { 
     cout<<strerror(errno); 
     close(socket_desc); 
     puts("Connect Error"); 
     return 1; 
    } 

    puts("Connected\n"); 

    receive_image(socket_desc); 

    close(socket_desc); 

    return 0; 
} 
+2

首先,記住一個JPEG文件是* binary *文件,它不能像文本文件那樣對待。要繼續,不要發送整個字符串'「Got it」'作爲回覆,'sizeof(int)!= strlen(buffer)'。最後,無論何時發送或接收字符串,請記住*終止*它們。 –

+0

在最後一個筆記中,您調用的許多函數可能比您報告的錯誤更多,並且如果在大多數情況下在套接字上發生「讀取」錯誤,則無法重試接收操作(相反,您最終可能會遇到一個無限的'read'循環)。 –

+0

請注意,'ftell()'返回'long',而不是'int'。和'read()'/'write()'返回'ssize_t',而不是'int'。功能的定義是有原因的。另外,請閱讀'sendfile()'手冊頁:http://man7.org/linux/man-pages/man2/sendfile.2.html –

回答

2

它可能來自你使用現有的每個FD的事實,因爲你永遠不會關閉任何文件描述符,並保持打開它們。你確定你從來沒有看到"Error Opening Image File"行作爲輸出嗎?如果你這樣做,那麼你只是嘗試fseek(NULL),這並不太好。

反正你的代碼中有很多奇怪的東西在進行。

爲什麼使用bzero()高於memset()

爲什麼使用printf(%c)顯示字符串而不是printf(%s)

編輯:也using namespace std;我認爲c沒有多大意義。

爲什麼使用

do{ 
    stat = write(socket, send_buffer, read_size); 
}while (stat < 0); 

含義你寫的,只要你有錯誤。同樣適用於閱讀。另外,寫入不一定總是一次寫入整個數據。這意味着你需要檢查它是否確實。

爲什麼要保留未使用的變量,如verify。 你應該使用編譯標誌來防止這些。如果您使用的是clang或gcc,則可以將-Wall -Wextra添加到編輯行中。

您可以嘗試使用valgrind查找錯誤:valgrind ./your_program your arguments它會爲您提供關於程序失敗的信息。如果你使用它,一定要把-g放到你的編譯行中來添加調試符號