Click here to Skip to main content
15,891,529 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am trying to send images to server. Earlier I had a simple function
void fileSend(const char* fpath)
This function is able to send one image file to the server. But, I am supposed to send many images to the server at once, that is why I went for vector<t>. I overloaded the previous method with
void fileSend(const vector<string>& fnames)
But now the program stops abruptly without sending any images. I tried finding the problem, but I am not able to understand what is happening. It fails in function
void fileSend(const vector<string>& fnames)
when I call the overloaded method
fileSend(fnames[k].c_str());
Please help

What I have tried:

void fileSend(const char *fpath)
	{
		// Extract only filename from given path.
		char filename[50];
		int i = strlen(fpath);
		for (; i > 0; i--)
		{
			if (fpath[i - 1] == '\\')
				break;
		}
		for (int j = 0; i <= (int)strlen(fpath); i++)
		{
			filename[j++] = fpath[i];
		}

		ifstream myFile(fpath, ios::in | ios::binary | ios::ate);
		int size = (int)myFile.tellg();
		myFile.close();

		char filesize[10]; itoa(size, filesize, 10);
		send(sock, filename, strlen(filename), 0);
		char rec[32] = ""; recv(sock, rec, 32, 0);

		send(sock, filesize, strlen(filesize), 0);
		recv(sock, rec, 32, 0);

		FILE *fr = fopen(fpath, "rb");

		while (size > 0)
		{
			char buffer[1030];

			if (size >= 1024)
			{
				fread(buffer, 1024, 1, fr);
				send(sock, buffer, 1024, 0);
				recv(sock, rec, 32, 0);
			}
			else
			{
				fread(buffer, size, 1, fr);
				buffer[size] = '\0';
				send(sock, buffer, size, 0);
				recv(sock, rec, 32, 0);
			}
			size -= 1024;
		}
		fclose(fr);
	}

	void fileSend(const vector<string>& fnames)
	{
		for (int k = 0; k < fnames.size(); k++)
		{
			fileSend(fnames[k].c_str()); // call the original function
		}
	}

I am calling this function in main() as:
vector<string> filenames;
	string path = "C:\\Images:\\";
	string imageName;
	string fullPath;
	int numberOfImages;

	while (true)
	{
		cout << "Enter the number of images you want to send : ";
		cin >> numberOfImages;

		for (int i = 0; i < numberOfImages; i++)
		{
			cout << "Select an image:";
			cin >> imageName;
			fullPath = path + imageName;
			filenames.push_back(fullPath);
		}

		client.fileSend(filenames);
}

client is an object of class Client where I have written the functions fileSend()
Posted
Updated 10-Sep-17 23:03pm
v3
Comments
CPallini 11-Sep-17 4:43am    
You should use the debugger to locate the problem.
Richard MacCutchan 11-Sep-17 12:18pm    
I explained to you yesterday that your loop should be around the vector, and pass each filename to the send function, one at a time.
raushanaj5 12-Sep-17 1:43am    
@Richard I did not understand
Richard MacCutchan 12-Sep-17 3:11am    
You have created a vector that contains a list of file names. All you need to do is iterate that vector (create a loop) and pass each filename to the function that sends it to the server.

the path sound weired:
string path = "C:\\Images:\\";
with the second ":"

Resolve this and debug the code.Maybe the overloaded call isnt resolved as you wish. Try to rename one function.
 
Share this answer
 
Comments
raushanaj5 11-Sep-17 4:46am    
@KarstenK I removed the colon from the path. But, still I am facing the same problem
There is no clear concept in your code and you are mixing C and C++ library functions for similar tasks (e.g. using C++ and C streams for file operations).

I don't see actually where and why your code fails, but here are some tips:

Your code does not check for errors. You should check the return value of each function that might return an error state and handle exceptions (e.g. when opening the a file with ifstream fails). Upon errors break execution and display an error message.

Getting a pointer to the file name for a given full path is quite simple (your code is much too complicated and there is no need for an additional buffer with const strings):
C++
const char * filename = strrchr(fpath, '\\');
if (filename)
    filename++;
else
    filename = fpath;

Then you are sending two strings but without the trailing NULL. How does the receiver should know how many bytes he has to read?
The common solution for this problem is sending the sizes first (as binary values and not as strings) followed by the content. Such an implementation is called a transfer protocol and should be defined before writing any code line. It is usally implemented by defining a structure. In your case it might look like:
C++
#include <stdint.h>

struct myprotocol {
    uint32_t namelen;
    uint32_t filesize;
    char filename[1];
};
It can be used like
C++
uint8_t buf[sizeof(myprotocol) + MAX_FILE_NAME_LEN];
prot * myprotocol = static_cast<myprotocol*>(buf);
prot->namelen = strlen(filename);
prot->filesize = filesize;
strcpy(prot->filename, filename);
if (send(socket, buf, sizeof(myprotocol) + prot->namelen, 0) < 0)
{
    // Report error here
    return; // May also return error indicator or code (errno) here
}
// Now send image data
The receiver can use a similar buffer and read sizeof(myprotocol) into that buffer. Then he can read namelen bytes at the corresponding buffer location followed by reading the image data:
C++
// Error checking omitted in this example!

// Receive the header
recv(socket, buf, sizeof(myprotocol), 0);
// Receive the remaining name characters (first already read above)
recv(socket, &prot->filename[1], prot->namelen, 0);
// Receive now prot->filesize image data bytes

The advantage of this method is that the receiver exactly knows how many bytes has been send and can provide or allocate buffers accordingly.

If your program still not works as expected then (showing no now provided error messages), you should run it within a debugger.
 
Share this answer
 

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