0
votes

I know C++ for quite long, but started using it for my purposes some what a year and a half ago. I started learning network programming on C++ and the first networking project is "File Transfering between hosts over TCP/IP" which sounds kind easy but I am stuck with sending data.

I am trying to send small buffer less than 4KB, so buffer[4096] works fine for me, but I am planning to expand this. WSAStartup(), socket(), bind(), listen(), accept() functions work fine and values for them are initialised for both Server and Client, but I am dealing with other problems, maybe recv(), send() etc. I still couldn't find the source of the problem.

Also it would be a ton helpful if somebody give me an example of transfering files over TCP/IP, but not in one packet, I want the file to be chunked and sent in parts or as it's called "ring model", but I couldn't find a working model;

P.S. This is first time I am asking here, pls give feedback about how well all of this is written, so that I could write more informative for community help, thanks)

Server

char* buffer = new char[4096];
ZeroMemory(buffer, sizeof(buffer));
ofstream file("a.txt", ios::binary);
int err = recv(conn, buffer, sizeof(buffer), 0);
file << buffer;
file.close();
if (err == 0)
{
    printf("Client diconnected...\n");
}

printf("Quitting...\n");
delete[] buffer;

Client

ifstream file("a.txt", ios::binary);
file.seekg(0, ios::end);
int size = file.tellg();
file.seekg(0, ios::beg);
char* buffer = new char[size];
file.read(buffer, size);
file.close();

int err = send(client, buffer, size, 0);
if (err == 0)
{
    printf("Disconnecting...\n");
}

printf("Quitting...\n");
delete[] buffer;

"a.txt" file on Client side is 45 bytes in here are 45 * 'a'

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

And this is what I get on Server side, file size is 14 bytes

aaaaaaaa ’pÈ/
4
You may find Boost Asio to be highly relevant for your use case.Eljay
You also want to pay attention to the fact that recv(sock, buffer, 4096, 0) doesn't receive 4096 bytes.user253751
You got the answer below. (sizeof problems). You also asked for feedback on your code. It's C++ but as it used to be written literally 25 years ago. C++ has moved on a lot. Since you learned it a long time ago you might be interested in buying a book that covers the newer aspects of C++. It's a far superior lanugage than it used to be (and this is coming from someone who always resists any change).john

4 Answers

2
votes

In C++, sizeof(buffer) is the size of the pointer type.

You may want to read up on more modern (as in after 1998) C++. We have std::vector nowadays, and that has a convenient size method. It would return 4096 for your buffer. Also, vector handles new[] and delete[] for you.

The fact that you get 8 "a"'s suggests that you built for x64. The remaining bytes are garbage; you should check how many bytes recv actually wrote to buffer. You cannot assume that you got all the bytes you asked for (whether that's 8 or 4096).

1
votes

I believe that sizeof(buffer) in this line -->

int err = recv(conn, buffer, sizeof(buffer), 0);

will return sizeof(char*) which is 4 bytes in a 32 bit program or 8 bytes in a 64 bits program instead of 4096 because it is not a static array as in you did not declare it as char buffer[4096]. So, either declare it as char buffer[4096] or convert the above code to

int err = recv(conn, buffer, 4096, 0);

1
votes

Two additional points:

  • TCP is a streaming protocol (not "message based"), so there's no guarantee that a single recv() will get everything sent in a single send().

  • The server line file << buffer; assumes buffer is zero terminated.

0
votes

MSDN state that :

If no error occurs, recv returns the number of bytes received and the buffer pointed to by the buf parameter will contain this data received. If the connection has been gracefully closed, the return value is zero.

Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recv

test if you actually read 45 bytes and check if there's an error (WSAGetLastError function)