使用raspberry pi和windows通过Cocket中的Socket发送图像(JPG)

时间:2015-12-21 14:25:23

标签: c

我正在编写一个C程序,以便能够使用TCP / IP套接字在raspberry pi和windows pc计算机之间(从服务器raspberry pi到客户端PC)连续传输图像文件,但似乎有一个发送第1017次后发生错误,服务器通过声明分段故障退出,我的意思是在我打算将图像文件发送到我的客户端2000次时,服务器退出第1017个图像。

服务器端

#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;
}

1 个答案:

答案 0 :(得分: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以添加调试符号