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

时间:2023-02-08 21:15:40

I'm writing a C program in order to be able to transfer an image file continously between raspberry pi and windows pc computer (from server raspberry pi to client pc) using TCP/IP sockets but there seems to be an error after sending for the 1017th time ,the server quits by stating segmentation fault , i mean in a loop when i intend to send the image file to my client 2000 times the server quits on 1017th image.

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

server side

服务器端

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

client side.

客户端。

#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 个解决方案

#1


2  

It may come from the fact that you use every fd available since you never close any file descriptor and keep opening them. Are you sure you never see the "Error Opening Image File" line as an output ? If you do, then you just try to fseek(NULL) and that doesn't work too well.

它可能来自于您使用每个可用的fd这一事实,因为您从不关闭任何文件描述符并继续打开它们。您确定永远不会看到“错误打开图像文件”行作为输出吗?如果你这样做,那么你只是尝试fseek(NULL),这不会很好。

There's a lot of weird stuff going on in your code anyway.

无论如何,你的代码中还有很多奇怪的东西。

Why do you use bzero() over memset() ?

为什么在memset()上使用bzero()?

Why do you use printf(%c) to display a string instead of printf(%s)

为什么使用printf(%c)来显示字符串而不是printf(%s)

Edit : Also using namespace std; doesn't make much sense in c I think.

编辑:也使用命名空间std;我觉得在c中没有多大意义。

Why do you use

你为什么用

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

Meaning you write as long as you have errors. Same goes for read. Also, write may not always write the whole data at once. Which means you need to check if it did.

只要你有错误就意味着你写。同样适合阅读。此外,写入可能并不总是一次写入整个数据。这意味着您需要检查它是否确实如此。

Why do you keep unused variables such as verify. You should probably use compiling flags to prevent these. If you're using clang or gcc, you could add -Wall -Wextra to your compilation line.

为什么要保留未使用的变量,例如验证。您应该使用编译标志来防止这些。如果您正在使用clang或gcc,则可以将-Wall -Wextra添加到编译行。

You could try to find the bug using valgrind : valgrind ./your_program your arguments It would provide you with information about where your program failed. If you use it, be sure to put -g in your compilation line to add debug symbols

您可以尝试使用valgrind找到错误:valgrind ./your_program您的参数它将为您提供有关程序失败位置的信息。如果使用它,请务必在编译行中添加-g以添加调试符号

#1


2  

It may come from the fact that you use every fd available since you never close any file descriptor and keep opening them. Are you sure you never see the "Error Opening Image File" line as an output ? If you do, then you just try to fseek(NULL) and that doesn't work too well.

它可能来自于您使用每个可用的fd这一事实,因为您从不关闭任何文件描述符并继续打开它们。您确定永远不会看到“错误打开图像文件”行作为输出吗?如果你这样做,那么你只是尝试fseek(NULL),这不会很好。

There's a lot of weird stuff going on in your code anyway.

无论如何,你的代码中还有很多奇怪的东西。

Why do you use bzero() over memset() ?

为什么在memset()上使用bzero()?

Why do you use printf(%c) to display a string instead of printf(%s)

为什么使用printf(%c)来显示字符串而不是printf(%s)

Edit : Also using namespace std; doesn't make much sense in c I think.

编辑:也使用命名空间std;我觉得在c中没有多大意义。

Why do you use

你为什么用

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

Meaning you write as long as you have errors. Same goes for read. Also, write may not always write the whole data at once. Which means you need to check if it did.

只要你有错误就意味着你写。同样适合阅读。此外,写入可能并不总是一次写入整个数据。这意味着您需要检查它是否确实如此。

Why do you keep unused variables such as verify. You should probably use compiling flags to prevent these. If you're using clang or gcc, you could add -Wall -Wextra to your compilation line.

为什么要保留未使用的变量,例如验证。您应该使用编译标志来防止这些。如果您正在使用clang或gcc,则可以将-Wall -Wextra添加到编译行。

You could try to find the bug using valgrind : valgrind ./your_program your arguments It would provide you with information about where your program failed. If you use it, be sure to put -g in your compilation line to add debug symbols

您可以尝试使用valgrind找到错误:valgrind ./your_program您的参数它将为您提供有关程序失败位置的信息。如果使用它,请务必在编译行中添加-g以添加调试符号