Click here to Skip to main content
15,890,741 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
hello,

i have designed a code for a tcp ip communication between raspberry pi and windows. the pi acts as a server and the pc acts as a client.
the server listens on the port for any incoming requests form the client side. as soon as it receives a request, it sends an image to the client.

the issue i have is,

the image on the server side is 56.5 kb

on the client i receive the image but it does not open. i get a "decode error". also the size of the image that the client recevies is 15kb.

What I have tried:

//server side

/* A simple server in the internet domain using TCP
   The port number is passed as an argument */

#include <stdio.h>
#include <string.h>
#include 
#include    
#include <unistd.h>  
#include <iostream>
#include <cstdlib>
#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");
    //picture = fopen("b.bmp", "r");
    printf("\nGetting 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));
    printf("Sending Picture with Size %d\n", size);

    //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: %s\n", read_buffer);
    //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));
    }
    
	return 0;
}


//#define myserver 5001; 

void error(const char *msg)
{
    perror(msg);
    exit(1);
    //return -1;
}

int main(int argc, char *argv[])
{
	 //int sockfd, newsockfd, portno=5001;
     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
	 int value=0;
	  //int n; 
     
     
    
     
     if (argc < 2)
      {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
         //return -1;
      }
      
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     
     if (sockfd < 0) 
        error("ERROR opening socket");
     else
     printf("socket created with %d %d",AF_INET, SOCK_STREAM);
     
     bzero((char *) &serv_addr, sizeof(serv_addr));
	 portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
    
    //listen on socket
              
     listen(sockfd,5);
     
     clilen = sizeof(cli_addr);
     
     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
                 
     if (newsockfd < 0) 
          error("ERROR on accept");
    
    
    //sending image on the socket
     
     /*while(value<2000)
     {     
			value=value+1;
			send_image(newsockfd);
     } */   
      send_image(newsockfd);   
     bzero(buffer,256);
     
      /*   n = read(newsockfd,buffer,255);
         if (n < 0) error("ERROR reading from socket");
         printf("Here is the message: %s\n",buffer);
         n = write(newsockfd,"I got your message",18);
        n = write(newsockfd,"Server-Message",14);
     */
     /*
     n = write(newsockfd,"Server-Message",512);
     if (n < 0) error("ERROR writing to socket");
     */
             
     close(newsockfd);
     close(sockfd);
     return 0; 
}


client side

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <string.h>
#include <winsock2.h> 
#include <iostream>
#include <fstream>
#include <errno.h>
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
//#include <conio.h>
#include 
#include 

//using namespace cv;
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 buffersize = 0, recv_size = 0, read_size, write_size, packet_index =1,stat; //size = 0
	char size[10241];
	char imagearray[10241],verify = '1';
	FILE *image;

//Find the size of the image

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

	cout<<"Packet received.\n";
	//printf("Packet size: %i\n",stat);
	cout<<"Image size: "<<sizeof(size)<<endl;
	

	char buffer[] = "Got it";

//Send our verification signal

	
	do
	{
		//stat = write(socket, &buffer, sizeof(int));
		stat = send(socket, buffer, sizeof(int),0);
	}while(stat<0);

	cout<<"Reply sent"<<endl<<endl;
	
	
	image = fopen("a.jpeg", "w");
	//image = fopen("a.bmp", "w");
	if( image == NULL)
	{
		cout<<"Error has occurred. Image file could not be opened"<<endl;
		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 < sizeof(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)
			 cout<<"error: bad file descriptor set"<<endl;

		if (buffer_fd == 0)
			cout<<"error: buffer read timeout expired."<<endl;

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

			cout<<"Packet number received: "<<packet_index<<endl;
			cout<<"Packet size: "<<read_size<<endl;


			//Write the currently read data into our image file
			write_size = fwrite(imagearray,1,read_size, image);
			cout<<"Written image size: "<<write_size<<endl; 

			if(read_size !=write_size)
			{
				cout<<"error in read write"<<endl;  
			}

			//Increment the total number of bytes read
			recv_size += read_size;
			packet_index++;
			cout<<"Total received image size: "<<recv_size<<endl<<endl<<endl;
			
		}
	}
	fclose(image);
	cout<<"Image successfully Received!"<<endl;
	return 1;
}



int main(int argc, char* argv[])
{
	// Initialize WinSock2.2 DLL
	// low word = major, highword = minor
	WSADATA wsaData = {0};
	WORD wVer = MAKEWORD(2,2);
	int nRet = WSAStartup( wVer, &wsaData );
	if( nRet == SOCKET_ERROR )
	{
		cout<<"Failed to init Winsock library";
		//cout << "Failed to init Winsock library" << endl;
		return -1;
	}
	cout << "Opening connection to server" << endl;
	WORD WSAEvent = 0;
	WORD WSAErr = 0;
	SOCKET hServer = {0};
	// open a socket
	//
	// for the server we do not want to specify a network address
	// we should always use INADDR_ANY to allow the protocal stack
	// to assign a local IP address
	hServer = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
	if( hServer == INVALID_SOCKET )
	{
		cout << "Invalid socket, failed to create socket" << endl;
		return -1;
	}
	// name a socket
	sockaddr_in saServer = {0};
	saServer.sin_family = PF_INET;
	saServer.sin_port = htons( 5001 );
	//saServer.sin_port = htons( 10000 );
	//saServer.sin_addr.s_addr = inet_addr( "127.0.0.2" );
	saServer.sin_addr.s_addr = inet_addr( "172.16.26.100" );

	// connect
	nRet = connect( hServer, (sockaddr*)&saServer, sizeof( sockaddr ) );
	if( nRet == SOCKET_ERROR ) 
	{
		cout << "Connection to server failed" << endl;
		closesocket( hServer );
		return -1;
	}
	cout << "Connected to server" << endl;
	cout << "Sending data to server" << endl;

	//recevie data from socket

	receive_image(hServer);

	//cout << "Data Echoed: " << wzRec << endl;
	cout << "Closing connection" << endl;

	// shutdown socket
	nRet = shutdown( hServer, SD_BOTH );
	if( nRet == SOCKET_ERROR ) 
	{
		// WSAGetLastError()
		cout << "Error trying to perform shutdown on socket" << endl;
		return -1;
	}
	
	// close server socket
	nRet = closesocket( hServer );
	hServer = 0;
	if( nRet == SOCKET_ERROR )
	{
		cout << "Error failed to close socket" << endl;
	}
	// Release WinSock DLL
	nRet = WSACleanup();
	if( nRet == SOCKET_ERROR )
	{
		cout << "Error cleaning up Winsock Library" << endl;
		return -1;
	}
	cout << "Data sent successfully" << endl;
	getchar();
	return 0;
}
Posted
Updated 30-Mar-16 22:50pm
v3

1 solution

Your server sends initially the image size as integer and it is received by the client and stored in the variable size.

What is printed by your client when it receives the size?
According to the line
C++
cout<<"Image size: "<<sizeof(size)<<endl;

it will not be the image size but the size of the size variable.

Similar when checking if all bytes has been received:
while( recv_size < sizeof(size))


Also your client size variable is of type char[10241]:
char size[10241];


So change the type of variable to int and remove the sizeof() in the above lines.

There may be still more errors but the above should be fixed first.

[EDIT]
Using comments another error has been found:
image = fopen("a.jpeg", "w");

This will open the file in text mode because that is the default mode with Windows. In this mode each line feed character (0x0A) will be prefixed with a carriage return (0x0D) when writing to the file. So the file should be opened in binary mode instead:
image = fopen("a.jpeg", "wb");

[/EDIT]
 
Share this answer
 
v2
Comments
violence666 31-Mar-16 5:03am    
hello,

i changed

char size[10241];

to

int size;

but i get an error in the following line

stat = recv(socket, *&size, sizeof(int),0);

Error 1 error C2664: 'recv' : cannot convert parameter 2 from 'int' to 'char *'

The format of the recv buffer is
https://msdn.microsoft.com/de-de/library/windows/desktop/ms740121(v=vs.85).aspx
Jochen Arndt 31-Mar-16 5:08am    
Just use casting and addressing like on the server side:

stat = recv(socket, (char*)&size, sizeof(size),0);

Note that I have also used sizeof(size) here. At this point it is better to use the variable name than the type (while using the type is still OK).
violence666 31-Mar-16 5:14am    
i did the following changes and i got the same image size on my client side. but when i try to open the image, i get a decoding error.
Jochen Arndt 31-Mar-16 5:19am    
I expected more errors (as already stated in my answer).

I suggest to copy the image file manually from the Pi to your PC and perform a binary file compare with the received image. You may use the 'fc' with option /B in a command shell on your PC for that. That may be helpful to find the error.
violence666 31-Mar-16 5:45am    
i did the same. the client image is larger (56.6kb) than the server image (56.4kb). im not sure if it has the hadnshake data (error correction) of the tcp connection.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900