简体   繁体   English

使用树莓派和Windows在C中通过Socket发送图像(JPG)

[英]Sending Image (JPG) through Socket in C using raspberry pi and windows

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套接字在树莓派和Windows pc计算机(从服务器树莓派到客户端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;
}

It may come from the fact that you use every fd available since you never close any file descriptor and keep opening them. 可能是由于您使用了所有可用的fd,因为您从未关闭任何文件描述符并一直打开它们。 Are you sure you never see the "Error Opening Image File" line as an output ? 您确定您永远不会看到"Error Opening Image File"行作为输出吗? If you do, then you just try to fseek(NULL) and that doesn't work too well. 如果这样做,那么您只需尝试fseek(NULL) ,效果就不太好。

There's a lot of weird stuff going on in your code anyway. 无论如何,您的代码中发生了很多奇怪的事情。

Why do you use bzero() over memset() ? 为什么在memset()使用bzero() memset()

Why do you use printf(%c) to display a string instead of printf(%s) 为什么使用printf(%c)而不是printf(%s)显示字符串

Edit : Also using namespace std ; 编辑:还using namespace std ; doesn't make much sense in c I think. 我认为在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 . 为什么要保留诸如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. 您可以尝试使用valgrind查找错误: valgrind ./your_program your arguments它会为您提供有关程序失败位置的信息。 If you use it, be sure to put -g in your compilation line to add debug symbols 如果使用它,请确保在编译行中放入-g以添加调试符号

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM