Reputation: 11
I've noticed there's a built-in function for C++ and C# and so, but C doesn't. (I'm on a windows machine).
So I wrote these two functions but they are not working, they just get stuck (I suspect it's the sending one because when the client's recieving he just gets an error according to the function return value).
Here are the functions (the sockets between the server and the client are working properly, I've tested it):
int recvFile(SOCKET s, const char* file_path)
{
FILE* fp = fopen(file_path, "wb");
char* file_buf = malloc(sizeof(char)*PACKAGE_LEN); //so it will be 0
int bytesRecieved, bytesWritten;
if(!fp)
{
fclose(fp);
free(file_buf);
return 1;
}
do
{
bytesRecieved = recv(s, file_buf, PACKAGE_LEN, 0); //receiving that file buffer in the size of PACKAGE_LEN (maximum chunk size).
if(bytesRecieved != PACKAGE_LEN)
{
fclose(fp);
free(file_buf);
return 1; //if there's an error...
}
if(!charPresent(file_buf, PACKAGE_LEN, EOF)) //as long as there's no EOF character in the file buffer received now.
{
fwrite(file_buf, sizeof(char), PACKAGE_LEN, fp); //write to file normally.
}
}
while(!charPresent(file_buf, PACKAGE_LEN, EOF)); // do it as long there's no EOF in the file buffer.
fwrite(file_buf, sizeof(char), indexOf(file_buf, PACKAGE_LEN, EOF), fp); //the last time you write the file buffer including the EOF is outside the loop.
fclose(fp);
free(file_buf);
return 0;
}
int charPresent(const char* str, size_t size, char ch)
{
int i;
for(i = 0 ; i < size ; i++)
{
if(str[i] == ch)
{
return 1;
}
}
return 0;
}
int indexOf(const char* str, size_t size, char ch)
{
int i;
for(i = 0 ; i < size ; i++)
{
if(str[i] == ch)
{
return i;
}
}
return -1;
}
(not much place to make a mistake when it comes to the function charPresent()
and IndexOf
though - I'm not using strlen()
on purpose because \0
is not promised to be in that buffer). and...:
int sendFile(SOCKET s, const char* file_path)
{
FILE* fp = fopen(file_path, "rb");
int i, err = 0, bytesSent, isOk = 1;
char* file_buf = malloc(sizeof(char)*PACKAGE_LEN);
char ch = 0;
if(!fp)
{
fclose(fp);
free(file_buf);
return 1;
}
while(ch != EOF && isOk)
{
i = 0;
do
{
do
{
err = ((fread(&ch, sizeof(char), 1, fp)) != 1);
file_buf[i] = ch;
}
while(err); //keep reading until read successfully.
i++;
if(i == PACKAGE_LEN) //means we achieved the maximum chunk size.
{
isOk = 0; //to exit the inner loop.
}
}
while(ch != EOF && isOk);
bytesSent = send(s, file_buf, PACKAGE_LEN, 0); //sending the file buffer over the socket.
if(bytesSent != PACKAGE_LEN)
{
fclose(fp);
free(file_buf);
return 1; //return an error (it is taken care of later on).
}
isOk = 1; // so the loop won't stop because we achieved only one chunk.
}
fclose(fp);
free(file_buf);
return 0;
}
What have I done wrong? :P
I thought of an alternate which is just to find out the length of the file and loop FILE_LEN/PACKAGE_LEN + ((!(FILE_LEN%PACKAGE_LEN))?(0):(1))
and in the last run just send the one with the EOF but basically it's the same concept, I think.
Upvotes: 0
Views: 145
Reputation: 182855
Your code's really not salvageable. You should honestly start over.
Before you write any code, have a look at some protocol specifications for other protocols that use TCP. You can look at FTP, HTTP, SMTP, and so on.
Pay particular attention to how they delimit messages. And keep in mind that TCP is a byte-stream protocol -- it does not preserve message boundaries.
I strongly advise you to go to the trouble of writing a specification. That way, if your code doesn't work, you can figure out which side is not complying with the specification. (If they both are, and it still doesn't work, the specification is broken.) Otherwise, there's no way to figure out what's wrong, because there's no statement of what's right.
Also, you can't use EOF
that way. There is no character that represents end of file. Every possible character value can be contained in a file. There's no "extra" character that can mean "end of file".
Upvotes: 2