Добавьте некоторую обработку ошибок в ваш код, который должен помочь вам отследить проблему.Также обратите внимание, что send()
, recv()
, fread()
и fwrite()
не гарантируют запись / чтение всего указанного вами буфера, поэтому вы должны принять это во внимание также.
Кроме того, так какTCP - это байтовый поток, сервер должен указать, когда файл заканчивается, чтобы клиент знал, когда прекратить чтение.Если вы не отправите размер файла перед отправкой фактического файла, единственный вариант - закрыть сокет после завершения передачи.
Попробуйте что-то вроде этого:
int send_all(int sock, const void *buf, int len)
{
const char *pbuf = (const char *) buf;
while (len > 0)
{
int sent = send(sock, pbuf, len, 0);
if (sent < 1)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes writable
// again before failing the transfer...
printf("Can't write to socket");
return -1;
}
pbuf += sent;
len -= sent;
}
return 0;
}
void str_server(int sock)
{
char buf[0x1000];
const char* filename = "test.text";
struct stat s;
if (stat(filename, &s) == -1)
{
printf("Can't get file info");
return;
}
FILE *file = fopen(filename, "rb");
if (!file)
{
printf("Can't open file for reading");
return;
}
// if you need to handle files > 2GB,
// be sure to use a 64bit integer, and
// a host-to-network function that can
// handle 64bit integers...
long size = s.st_size;
long tmp_size = htonl(size);
if (send_all(sock, &tmp_size, sizeof(tmp_size)) == 0)
{
while (size > 0)
{
int rval = fread(buf, 1, min(sizeof(buf), size), file);
if (rval < 1)
{
printf("Can't read from file");
break;
}
if (send_all(sock, buf, rval) == -1)
break;
size -= rval;
}
}
fclose(file);
}
int write_all(FILE *file, const void *buf, int len)
{
const char *pbuf = (const char *) buf;
while (len > 0)
{
int written = fwrite(pbuf, 1, len, file);
if (written < 1)
{
printf("Can't write to file");
return -1;
}
pbuf += written;
len -= written;
}
return 0;
}
int read_all(int sock, void *buf, int len)
{
char *pbuf = (char *) buf;
int total = 0;
while (len > 0)
{
int rval = recv(sock, pbuf, len, 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
return -1;
}
if (rval == 0)
{
printf("Socket disconnected")
return 0;
}
pbuf += rval;
len -= rval;
total += rval;
}
return total;
}
void RecvFile(int sock, const char* filename)
{
int rval;
char buf[0x1000];
FILE *file = fopen(filename, "wb");
if (!file)
{
printf("Can't open file for writing");
return;
}
// if you need to handle files > 2GB,
// be sure to use a 64bit integer, and
// a network-to-host function that can
// handle 64bit integers...
long size = 0;
if (read_all(sock, &size, sizeof(size)) == 1)
{
size = ntohl(size);
while (size > 0)
{
rval = read_all(sock, buf, min(sizeof(buf), size));
if (rval < 1)
break;
if (write_all(file, buf, rval) == -1)
break;
}
}
fclose(file);
}