File transfer via socket

If the file is smaller than 1500 bytes, there's no problem. But if it's larger than 1500, I have to split the file in chunks of 1500 bytes (default packet size). Now, it sends the file perfectly, but I have to close the receiver before it actually writes.

Sender:
1
2
3
4
5
while(SizeCheck < FileSize){
	int Read = fread_s(mfcc, 1499, sizeof(char), 1499, fp);
	send(Socket, mfcc, Read, 0);
	SizeCheck += Read;
}


Receiver:
1
2
3
4
5
while(SizeCheck < FileSize){
		int Received = recv(mySocket, mfcc, 1499, 0);
		fwrite(mfcc, 1, Received, fp);
		SizeCheck += Received;
	}


After the while loop, there's
1
2
3
fclose(fp);
Sleep(500);
free(mfcc);


Also, I put this in the loop:
printf("Filesize: %d\nSizecheck: %d\nReceived: %d\n\n", FileSize, SizeCheck, Received);

Returns:
Filesize: 4874
Sizecheck: 1260
Received: 1260

Filesize: 4874
Sizecheck: 2759
Received: 1499

Filesize: 4874
Sizecheck: 4258
Received: 1499

Filesize: 4874
Sizecheck: 4526
Received: 268
Your code assumes that send/recv send all the data given to it. This is not the case. You have to check how much was sent/received and loop, until it's all gone.
I do that.

1
2
3
4
5
6
7
int Received = recv(mySocket, mfcc, 1499, 0);
fwrite(mfcc, 1, Received, fp);



int Read = fread_s(mfcc, 1499, sizeof(char), 1499, fp);
send(Socket, mfcc, Read, 0);


As far as I know, recv(), send() and fread_s() return how much they actually wrote/sent/received.
Not with the send you don't.
Not? What is this then?
1
2
int Read = fread_s(mfcc, 1499, sizeof(char), 1499, fp);
send(Socket, mfcc, Read, 0);
This is ignoring send's return value.
Oh wait. *facepalms* I get what you guys mean. I'll check it.

EDIT: Nope, same thing.
Last edited on
You should call fflush after each fwrite.
Done. Now, what could be the problem? D:

Sender:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void DownloadFile(SOCKET Socket){
	if(Socket == NULL){
		return;
	}
	while(1){
		char filename[1024];
		recv(Socket, filename, sizeof(filename), 0);
		if(filename[0] == '.'){
			break;
		}
		FILE* fp = fopen(filename, "r");
		fseek(fp, 0, SEEK_END);
		long FileSize = ftell(fp);
		char GotFileSize[1024];
		_itoa_s(FileSize, GotFileSize, 10);
		send(Socket, GotFileSize, 1024, 0);
		rewind(fp);
		long SizeCheck = 0;
		char* mfcc;
		if(FileSize > 1499){
			mfcc = (char*)malloc(1500);
			while(SizeCheck < FileSize){
				int Read = fread_s(mfcc, 1500, sizeof(char), 1500, fp);
				int Sent = send(Socket, mfcc, Read, 0);
				SizeCheck += Sent;
			}
		}
		else{
			mfcc = (char*)malloc(FileSize + 1);
			fread_s(mfcc, FileSize, sizeof(char), FileSize, fp);
			send(Socket, mfcc, FileSize, 0);
		}
		fclose(fp);
		Sleep(500);
		free(mfcc);
	}
	return;
}


Receiver:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void DownloadFile(SOCKET Socket){
	if(Socket == NULL){
		return;
	}
	while(1){
		printf("Input local filename: ");
		char localfile[1024];
		gets_s(localfile, 1024);
		if(localfile[0] == '.'){
			send(Socket, localfile, sizeof(localfile), 0);
			break;
		}
		printf("Input remote filename: ");
		char filename[1024];
		gets_s(filename, 1024);
		if(filename[0] == '.'){
			send(Socket, filename, sizeof(filename), 0);
			break;
		}
		send(Socket, filename, sizeof(filename), 0);
		char GotFileSize[1024];
		recv(Socket, GotFileSize, 1024, 0);
		long FileSize = atoi(GotFileSize);
		long SizeCheck = 0;
		FILE *fp = fopen(localfile, "w");
		char* mfcc;
		if(FileSize > 1499){
			mfcc = (char*)malloc(1500);
			while(SizeCheck < FileSize){
				int Received = recv(Socket, mfcc, 1500, 0);
				SizeCheck += Received;
				fwrite(mfcc, 1, Received, fp);
				fflush(fp);
				printf("Filesize: %d\nSizecheck: %d\nReceived: %d\n\n", FileSize, SizeCheck, Received);
			}
		}
		else{
			mfcc = (char*)malloc(FileSize + 1);
			int Received = recv(Socket, mfcc, FileSize, 0);
			fwrite(mfcc, 1, Received, fp);
			fflush(fp);
		}
		fclose(fp);
		Sleep(500);
		free(mfcc);
	}
}
Last edited on
Giving this a bump. :<
You're still assuming that send sends all the data at once. By putting the file read in the same loop, you're changing the buffer each time you loop. I thought that was obvious.
1
2
3
int Read = fread_s(mfcc, 1500, sizeof(char), 1500, fp);
int Sent = send(Socket, mfcc, Read, 0);
SizeCheck += Sent;


Also, it is sending the whole buffer. Because, if I close the receiver, the new file is a copy of the old one. The problem is that I have to close the receiver first.
I still don't understand why you're using that 1500 byte limit. You shouldn't have to worry about the size of an ethernet frame.

You really should figure out why your send fails if you try to send more than an ethernet frame's worth at a time.

Can you post the socket initialisation code too. Maybe there's something in there.
I read that the default packet size for TCP sockets is 1500 bytes.

Here are the socket initialisation codes.

Sender:
1
2
3
4
5
6
7
8
9
10
11
12
SOCKET clientSocket;
WSADATA myData;
SOCKADDR_IN myAddress;
WORD version = MAKEWORD(2, 0);
WSAStartup(version, &myData);
clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
myAddress.sin_addr.s_addr = inet_addr("127.0.0.1"); // Just for testing purposes
myAddress.sin_family = AF_INET;
myAddress.sin_port = htons(6000);
while(connect(clientSocket, (SOCKADDR*)&myAddress, sizeof(myAddress)) == SOCKET_ERROR){
	connect(clientSocket, (SOCKADDR*)&myAddress, sizeof(myAddress));
}


Receiver:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SOCKET mySocket;
WSADATA myData;
SOCKADDR_IN myAddress;
WORD version;
version = MAKEWORD(2, 0);
WSAStartup(version, &myData);
mySocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
myAddress.sin_addr.s_addr = INADDR_ANY;
myAddress.sin_family = AF_INET;
myAddress.sin_port = htons(6000);
if(bind(mySocket, (SOCKADDR*)&myAddress, sizeof(myAddress)) == SOCKET_ERROR){
	printf("Socket did not bind!");
	WSACleanup();
	Sleep(1000);
	return 0;
}
listen(mySocket, 10);
int size = sizeof(myAddress);
mySocket = accept(mySocket, (SOCKADDR*)&myAddress, &size);
I read that the default packet size for TCP sockets is 1500 bytes.

You might want to go back to your source and re-read that. It's not true. You may be confusing it with the size of an ethernet frame.

It looks ok, but I don't know why loop on calling connect.

You really need to sort out that send code. You get away with your recv by good fortune.
I can't find the source anymore. But I'm sure it said something like: "The default packet size for TCP sockets is 1500 bytes". Anyways, if it doesn't matter, I will use 10240 as the limit. Or no limit at all?

Why I have a connect loop: The sender isn't online 24/7, so loop until it is online.

Apparently, it receives less bytes than it should, but there's nothing missing in the new file. It's a replica, accurate to the byte.
Last edited on
I think I know why it screws up. For testing purposes, I'm sending the .cpp file of the sender. Now, I created a .txt file of about the same size, with random Latin letters in there. Like the alphabet as we know it.
This transfers perfectly. So there's nothing wrong with the loop or whatsoever. It automatically ends the loop and prompts me for another filename. Because of this, I think there are some characters in the Send.cpp file that are larger than 1 byte.
But there's something that doesn't make sense. How come the new file is exactly the same size as the original, with no single character missing?

Anyways, I checked the return values, and this part of code (sender):
1
2
3
4
5
6
7
8
9
if(FileSize > 4095){
	mfcc = (char*)malloc(4096);
	while(SizeCheck < FileSize){
		int Read = fread_s(mfcc, 4096, sizeof(char), 4096, fp);
		int Sent = send(Socket, mfcc, Read, 0);
		SizeCheck += Sent;
		printf("Filesize: %d\nSizecheck: %d\nRead: %d\nSent: %d\n\n", FileSize, SizeCheck, Read, Sent);
	}
}


returns this:
Filesize: 4905
Sizecheck: 4096
Read: 4096
Sent: 4096

Filesize: 4905
Sizecheck: 4714
Read: 618
Sent: 618

Filesize: 4905
Sizecheck: 4714
Read: 0
Sent: 0


The part where Read and Sent are 0 repeats all the time.
Now, the receiver part:
1
2
3
4
5
6
7
8
9
if(FileSize > 4095){
	mfcc = (char*)malloc(4096);
	while(SizeCheck < FileSize){
		int Received = recv(mySocket, mfcc, 4096, 0);
		int Written = fwrite(mfcc, sizeof(char), Received, fp);
		SizeCheck += Written;
		printf("Filesize: %d\nSizecheck: %d\nReceived: %d\nWritten: %d\n\n", FileSize, SizeCheck, Received, Written);
	}
}


returns:

Filesize: 4905
Sizecheck: 4096
Received: 4096
Written: 4096

Filesize: 4905
Sizecheck: 4714
Received: 618
Written: 618
Fixed it. A newline is 2 bytes in size, but my program only counted it as one. I figured this because the difference between Filesize and Sizecheck is in fact the amount of lines in the file.

New loop:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
char* mfcc;
mfcc = (char*)malloc(FileSize + 1);
while(SizeCheck < FileSize){
	int Received = recv(mySocket, mfcc, FileSize, 0);
	int Written = fwrite(mfcc, sizeof(char), Received, fp);
	SizeCheck += Written;
	for(int i = 0; i < Written; i++){
		if(mfcc[i] == '\n'){
			SizeCheck += 1;
		}
	}
}
fclose(fp);
free(mfcc);


The sender part of this code is like this one.

Thanks for the help all. :3

Case closed. :D
Last edited on
You should open the file as binary on a Microsoft platform. DOS/Unix '\n' difference is an old problem.
Kay. :3
Last edited on
Topic archived. No new replies allowed.