2015-12-21 65 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放到你的编译行中来添加调试符号