I am able to send an image from client to server and I got the image on server. However, when I am trying to open the image on server side it's damaged even though it has the original size ( not lost anything ). In fact I asked on this website about previous errors and I got help--- see the link below: Socket Programming -- Sending and receiving images
Now I want to fix why image after I received it is damaged. This is my last code --
Server side written in c++:
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <fstream>
using namespace std;
using namespace cv;
#define SERVER_PORT htons(50007)
int main() {
/* First call to socket() function */
int serverSock=socket(AF_INET, SOCK_STREAM, 0);
if (serverSock < 0)
{
perror("ERROR opening socket");
exit(1);
}
sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = SERVER_PORT;
serverAddr.sin_addr.s_addr = INADDR_ANY;
/* bind (this socket, local address, address length)
bind server socket (serverSock) to server address (serverAddr).
Necessary so that server can use a specific port */
/* Now bind the host address using bind() call.*/
if (bind(serverSock, (struct sockaddr *)&serverAddr, sizeof(sockaddr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here process will
* go in sleep mode and will wait for the incoming connection
*/
// wait for a client
/* listen (this socket, request queue length) */
listen(serverSock,5);
sockaddr_in clientAddr;
socklen_t sin_size=sizeof(struct sockaddr_in);
int clientSock=accept(serverSock,(struct sockaddr*)&clientAddr, &sin_size);
if (clientSock < 0)
{
perror("ERROR on accept");
exit(1);
}
//char *buff = (char*)malloc(sizeof(char) * (240*360));
FILE* output = fopen("test.jpeg", "wb");
//this is the total number of bytes ever read from the socket
unsigned int readBytes = 0;
while(true)
{
std::size_t buffer_size = 1024;
char buffer[1024];
int ret = recv(clientSock, buffer, buffer_size, 0);
if (ret == 0)
break;
if (ret < 0)
{
perror("ERROR reading from socket");
exit(1);
}
fwrite(buffer, sizeof(char), ret, output);
readBytes += ret;
}
fclose( output );
std::ifstream infile("test.jpeg", std::ios::binary);
char filepath[512];
infile.read(filepath, 512);
if( infile.gcount() != 512 )
perror("Data did not send filepath");
std::string filepathstr(filepath);
std::cout << filepathstr << std::endl;
std::ofstream ofile(filepathstr);
//loop until there is nothing left to read or error on the filestream
while (infile && ofile)
{
std::size_t buffer_size = 1024;
char buffer[1024];
infile.read(buffer, buffer_size);
int ret = infile.gcount();
ofile.write(buffer,ret);
}
ofile.close();
close(serverSock);
return 0;
}
Client side written in python:
import socket
import sys,os
import cv2
import numpy as np
import time
HOST, PORT = "localhost", 50007
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Create Socket
client_socket.connect((HOST, PORT)) # Connection
fpath ='/Users/salemalqahtani/Desktop/NetworkingPart/client/ss.png'
size = os.path.getsize(fpath)
print size
client_socket.send(str.encode("STORE " + fpath))
t = time.time()
pic = open(fpath,'rb')
while True:
strng = pic.readline(512)
if not strng:
break
client_socket.send(strng)
pic.close()
print("Done sending")
print("Elapsed time = " + str(time.time() - t) + 's')
client_socket.close()
Please I appreciate your help.
I could reproduce your error very easily on my PC.
On the sender side, in python, you start with sending the name of the file:
client_socket.send(str.encode("STORE " + fpath))
Every bytes of this string are transfered and only these bytes. But this is immediately followed by the content of the file. First comes the PNG header which is 0x89 followed by the three letters PNG, followed by binary data:

On the receiver side, you receive all the data, write it to a file, and then you consider that the 512 first are the file name. Unfortunately, you take much more than only the file name ! As you write the rest of the data as being the png file, your resulting file does no longer have a valid png header.
By the way, you use an intermediary file (is this really needed ?). You open it correctly in "wb" binary mode. But your end result file is opened as a stream in default text mode. Here you should go the safe way:
std::ofstream ofile(filepathstr, std::ios::binary);
You have to take into account the streamng nature of a socket. When you send data, nothing will tell the receiver how long the data is supposed to be (except the count of bytes received, if the comunication is not interrupted).
So three solutions:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With