So, I have a working socket. I'm basically making a socket to allow me to transfer files from one program to another program. Everything is working except on the client side, it won't create the file?
Server:
int main() {
WSADATA Winsock;
SOCKET Socket, Sub;
Addr addr;
IncomingAddress incomingAddress;
int AddressLen = sizeof(IncomingAddress);
// Start up Winsock
WSAStartup(MAKEWORD(2, 2), &Winsock);
if (LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) {
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Memset alternative
ZeroMemory(&addr, sizeof(Addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(portNumber);
bind(Socket, (sockaddr*) &addr, sizeof(Addr));
if (listen(Socket, 1) == SOCKET_ERROR) {
printf("Listening error!\n");
} else {
printf("Listening...\n");
}
if (Sub = accept(Socket, (sockaddr*) &incomingAddress, &AddressLen)) {
char *ClientIP = inet_ntoa(incomingAddress.sin_addr);
int ClientPort = ntohs(incomingAddress.sin_port);
printf("Client connected!\n");
printf("IP: %s:%d\n", ClientIP, ClientPort);
printf("Sending file... \n");
FILE *File;
char *Buffer;
unsigned long Size;
File = fopen("test.txt", "rb+");
if (!File) {
printf("Error while reading the file!\n");
getchar();
return 0;
}
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);
Buffer = malloc(Size);
fread(Buffer, Size, 1, File);
char cSize[MAX_PATH];
sprintf(cSize, "%i", Size);
fclose(File);
send(Sub, cSize, MAX_PATH, 0); // File size
}
return 0;
}
Client:
int main() {
WSADATA Winsock;
SOCKET Socket;
Addr addr;
IncomingAddress incomingAddress;
int AddressLen = sizeof(IncomingAddress);
WSAStartup(MAKEWORD(2, 2), &Winsock);
if (LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) {
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&addr, sizeof(Addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(6000);
if (connect(Socket, (sockaddr*) &addr, sizeof(Addr)) < 0) {
printf("Connection Failed!\n");
getchar();
return 0;
}
printf("Connection successful! \n");
printf("Receiving file... \n");
int Size;
char *Filesize = malloc(1024);
if (recv(Socket, Filesize, 1024, 0)) { // File Size
Size = atoi((const char*) Filesize);
printf("File size: %d\n", Size);
}
char *Buffer = malloc(Size);
int Offset = 0;
while (Size > Offset) {
int Amount = recv(Socket, Buffer + Offset, Size - Offset, 0);
if (Amount <= 0) {
printf("Error: " + WSAGetLastError());
break;
} else {
Offset += Amount;
printf("2\n");
}
}
FILE *File;
File = fopen("test.txt", "wb+");
fwrite(Buffer, 1, Size, File);
fclose(File);
getchar();
closesocket(Socket);
WSACleanup();
return 0;
}
You're sending merely the lenght of the file, but not the file itself to the client:
send(Sub, cSize, MAX_PATH, 0); // File size
This never recieves anything:
int Amount = recv(Socket, Buffer + Offset, Size - Offset, 0);
So yeah, just send the actual file as well.
Related
I am trying to download mp4 video using C socket. File downloaded successfully but when i am try to play it is not working. File is same as original file size. But their checksum is differents. But this code is working fine for pdf file.
I am grateful and appreciate for your afford.
int main() {
int socket_desc;
char *message;
char server_reply[100000];
char *file_path = "file.mp4";
ssize_t total_len = 0;
char *ip = NULL;
FILE *file = NULL;
struct sockaddr_in server;
//Create socket
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
printf("dCould not create socket");
}
server.sin_addr.s_addr = inet_addr("195.154.200.24");
server.sin_family = AF_INET;
server.sin_port = htons(80);
if (connect(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) {
printf("connect error");
return 1;
}
message = "GET /upload_file/367/382/Indian%20Pop%20Hit%20Video%20Songs/Indian%20Pop%20Video%20Songs%202016%20-%20MP4/Jammin%20-%20Yaara%20-%20A%20R%20Rahman%20-%20Video%20MP4.mp4 HTTP/1.1\r\nHost: dl.pagal.link\r\n\r\n";
if (send(socket_desc, message, strlen(message), 0) < 0) {
printf("Send failed");
return 1;
}
remove( file_path );
file = fopen( file_path , "ab");
if (file == NULL) {
printf("File %s could not opened", file_path);
return 1;
}
while (1) {
ssize_t received_len = recv(socket_desc, server_reply, sizeof(server_reply), 0);
if (received_len < 0) {
printf("Received failed\n");
return -1;
}
if (received_len == 0) {
break;
}
fwrite(server_reply, (size_t) received_len, 1, file);
}
fclose(file);
return 0;
}
So, I'm making a socket program to connect two programs and everything works thus far; setting up winsock, connecting and interaction. However, the file being sent over from the client side to the server side has weird characters in it.
Example:
File: test.txt
Contents: Hey, how are you?
** Client sends file over to Server **
Expected Output: Hey, how are you?
Actual Output: 7_ Ä _
Server code:
int main() {
WSADATA Winsock;
SOCKET Socket, Sub;
Addr addr;
IncomingAddress incomingAddress;
int AddressLen = sizeof(IncomingAddress);
// Start up Winsock
WSAStartup(MAKEWORD(2, 2), &Winsock);
if (LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) {
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Memset alternative
ZeroMemory(&addr, sizeof(Addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(portNumber);
bind(Socket, (sockaddr*) &addr, sizeof(Addr));
if (listen(Socket, 1) == SOCKET_ERROR) {
printf("Listening error!\n");
} else {
printf("Listening...\n");
}
if (Sub = accept(Socket, (sockaddr*) &incomingAddress, &AddressLen)) {
int Size;
char *Filesize = malloc(MAX_PATH);
if (recv(Socket, Filesize, MAX_PATH, 0)) { // File Size
Size = atoi((const char*) Filesize);
printf("File size: %d\n", Size);
}
char *Buffer = malloc(Size);
int Offset = 0;
while (Size > Offset) {
printf("TESST");
int Amount = recv(Socket, Buffer + Offset, Size - Offset, 0);
if (Amount <= 0) {
printf("Error: " + WSAGetLastError());
break;
} else {
Offset += Amount;
}
}
FILE *File;
File = fopen("test.txt", "wb+");
fwrite(Buffer, 1, Size, File);
fclose(File);
getchar();
closesocket(Socket);
WSACleanup();
}
}
return 0;
}
Client code:
int main() {
WSADATA Winsock;
SOCKET Socket, Sub;
Addr addr;
IncomingAddress incomingAddress;
int AddressLen = sizeof(IncomingAddress);
WSAStartup(MAKEWORD(2, 2), &Winsock);
if (LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) {
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&addr, sizeof(Addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(6000);
if (connect(Socket, (sockaddr*) &addr, sizeof(Addr)) < 0) {
printf("Connection Failed!\n");
getchar();
return 0;
}
char *ClientIP = inet_ntoa(incomingAddress.sin_addr);
int ClientPort = ntohs(incomingAddress.sin_port);
printf("Client connected!\n");
printf("IP: %s:%d\n", ClientIP, ClientPort);
printf("Sending file... \n");
FILE *File;
char *Buffer;
unsigned long Size;
File = fopen("test.txt", "rb+");
if (!File) {
printf("Error while reading the file!\n");
getchar();
return 0;
}
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);
Buffer = malloc(Size);
fread(Buffer, Size, 1, File);
char cSize[MAX_PATH];
sprintf(cSize, "%i", Size);
fclose(File);
send(socket, cSize, MAX_PATH, 0); // File size
int Offset = 0;
while (Size > Offset) {
int Amount = send(Sub, Buffer + Offset, Size - Offset, 0);
if (Amount <= 0) {
printf("Error: " + WSAGetLastError());
break;
} else {
Offset += Amount;
}
}
free(Buffer);
closesocket(Sub);
closesocket(Socket);
WSACleanup();
printf("File sent!\n");
return 0;
}
You have three problems, one in the client and two in the server.
In the client you are sending the size of the file through Socket, which is correct. But then you use the unconnected and uninitialized socket Sub to send the data of the file.
In the server you have almost the opposite problem, where you attempt to receive both the size and the data through the passive listening socket instead of the accepted connection socket Sub.
Also in the server, if there's an error when reading the data you report it, but then you write data to the file anyway. In this case it will be some uninitialized data of unknown length.
Use correct sockets, and if there's an error don't do things you should not do.
And actually do some error checking. When receiving the size in the server, you don't check for errors, just that the connection wasn't closed by the other end of the connection.
I'm writing the barebones of a web server, but I can't figure out why my file isn't be sent over my socket, I'm connecting to it and everything it just not send()ing my file... What am I missing?
//CODE (server.c)
#include<netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
int main(void) {
int create_socket, new_socket;
socklen_t addrlen;
int bufsize = 1024;
char *buffer = malloc(bufsize);
struct sockaddr_in address;
if ((create_socket = socket(AF_INET, SOCK_STREAM, 0)) > 0){
printf("The socket was created\n");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(80);
if (bind(create_socket, (struct sockaddr *) &address, sizeof(address)) == 0){
printf("Binding Socket\n");
}
long fsize;
FILE *fp = fopen("index.html", "r");
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
rewind(fp);
char *msg = malloc(fsize + 1);
fread(msg, sizeof(msg), 1, fp);
while (1) {
if (listen(create_socket, 10) < 0) {
perror("server: listen");
exit(1);
}
if ((new_socket = accept(create_socket, (struct sockaddr *) &address, &addrlen)) < 0) {
perror("server: accept");
exit(1);
}
if (new_socket > 0){
printf("The Client is connected...\n");
}
recv(new_socket, buffer, bufsize, 0);
printf("%s\n", buffer);
write(new_socket, "HTTP/1.1 200 OK\n", 16);
write(new_socket, "Content-length: 46\n", 19);
write(new_socket, "Content-Type: text/html\n\n", 25);
/* write(new_socket, "<html><body><H1>Hello world</H1></body></html>",46); */
if((send(new_socket, msg, fsize+1, 0)) > 0){
printf("success");
}
else{
printf("failed");
}
close(new_socket);
}
close(create_socket);
return 0;
}
//FILE (index.html) *same directory
<html>
<body>
<h1>Hello World</h1>
</body>
</html>
The code is completely broken, for a dozen different reasons. Try something more like this instead:
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
bool writeDataToClient(int sckt, const void *data, int datalen)
{
const char *pdata = (const char*) data;
while (datalen > 0){
int numSent = send(sckt, pdata, datalen, 0);
if (numSent <= 0){
if (numSent == 0){
printf("The client was not written to: disconnected\n");
} else {
perror("The client was not written to");
}
return false;
}
pdata += numSent;
datalen -= numSent;
}
return true;
}
bool writeStrToClient(int sckt, const char *str)
{
return writeDataToClient(sckt, str, strlen(str));
}
int main(void){
int create_socket, new_socket;
char *buffer;
int bufsize = 1024;
struct sockaddr_in address;
socklen_t addrlen;
buffer = (char*) malloc(bufsize);
if (!buffer){
printf("The receive buffer was not allocated\n");
exit(1);
}
create_socket = socket(AF_INET, SOCK_STREAM, 0);
if (create_socket == -1){
perror("The socket was not created");
exit(1);
}
printf("The socket was created\n");
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(80);
if (bind(create_socket, (struct sockaddr *) &address, sizeof(address)) == -1){
perror("The socket was not bound");
exit(1);
}
printf("The socket is bound\n");
long fsize;
FILE *fp = fopen("index.html", "rb");
if (!fp){
perror("The file was not opened");
exit(1);
}
printf("The file was opened\n");
if (fseek(fp, 0, SEEK_END) == -1){
perror("The file was not seeked");
exit(1);
}
fsize = ftell(fp);
if (fsize == -1) {
perror("The file size was not retrieved");
exit(1);
}
rewind(fp);
char *msg = (char*) malloc(fsize);
if (!msg){
perror("The file buffer was not allocated\n");
exit(1);
}
if (fread(msg, fsize, 1, fp) != 1){
perror("The file was not read\n");
exit(1);
}
fclose(fp);
printf("The file size is %ld\n", fsize);
if (listen(create_socket, 10) == -1){
perror("The socket was not opened for listening");
exit(1);
}
printf("The socket is listening\n");
while (1) {
addrlen = sizeof(address);
new_socket = accept(create_socket, (struct sockaddr *) &address, &addrlen);
if (new_socket == -1) {
perror("A client was not accepted");
exit(1);
}
printf("A client is connected from %s:%hu...\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
// I will leave it as an exercise for you to implement
// a proper HTTP request parser here...
int numRead = recv(new_socket, buffer, bufsize, 0);
if (numRead < 1){
if (numRead == 0){
printf("The client was not read from: disconnected\n");
} else {
perror("The client was not read from");
}
close(new_socket);
continue;
}
printf("%.*s\n", numRead, buffer);
if (!writeStrToClient(new_socket, "HTTP/1.1 200 OK\r\n")){
close(new_socket);
continue;
}
char clen[40];
sprintf(clen, "Content-length: %ld\r\n", fsize);
if (!writeStrToClient(new_socket, clen)){
close(new_socket);
continue;
}
if (!writeStrToClient(new_socket, "Content-Type: text/html\r\n")){
close(new_socket);
continue;
}
if (!writeStrToClient(new_socket, "Connection: close\r\n\r\n") == -1){
close(new_socket);
continue;
}
//if (!writeStrToClient(new_socket, "<html><body><H1>Hello world</H1></body></html>")){
if (!writeDataToClient(new_socket, msg, fsize)){
close(new_socket);
continue;
}
printf("The file was sent successfully\n");
close(new_socket);
}
close(create_socket);
return 0;
}
fsize = ftell(fp);
rewind(fp);
char *filebuff = malloc(fsize + 1);
Why fsize+1? You don't need the +1.
fread(filebuff, sizeof(filebuff), 1, fp);
Unchecked return value. The second argument should be fsize. At present you're only passing the sizeof the pointer.
//create/bind socket
if ((create_socket = socket(AF_INET, SOCK_STREAM, 0)) > 0)
{
printf("The socket was created\n");
}
If the socket creation fails you must (a) print a proper error message as described below and (b) not just continue with execution as though the error hadn't occurred.
if (bind(create_socket, (struct sockaddr *) &address, sizeof(address)) == 0)
{
printf("Binding Socket\n");
}
Ditto.
//listen, create new_sock, write headers, send file
while (1){
if (listen(create_socket, 10) < 0) {
perror("server: listen");
exit(1);
}
The listen() call should be ahead of the loop, not inside it. This is the first time you've actually handled a failure case.
new_sock = accept(sock, (struct sockaddr *) &address, &addrlen);
recv(new_socket, buffer, bufsize, 0);
printf("%s\n", buffer);
Invalid. Unchecked return code. The buffer is only valid at all if recv() returned a positive integer, and only that many bytes of it are valid. It should be:
int count = recv(new_socket, buffer, bufsize, 0);
printf("%.*s\n", count, buffer);
Then we start on HTTP:
write(new_sock, "HTTP/1.1 200 OK\n", 16);
write(new_sock, "Content-length: 46\n", 19);
write(new_sock, "Content-Type: text/html\n\n", 25);
The line terminator in HTTP is inherited from Telnet and it is specified as \r\n, not \n.
if(send(new_sock, filebuff, fsize+1, 0) > 0){
printf("success");
}
else{
printf("failed");
}
Inadequate. If you get an error from any system call, you must call perror(), or use errno or strerror() in an error message. "Failed" conveys no useful information, and debugging becomes a mere guessing game. Don't write code like this. You should use perror() or whatever you decide for all the other unchecked return values above.
But there is a bigger problem. You're assuming that the file fits into memory. There is no need for that assumption. Just copy the file using an 8k buffer as follows:
int count;
while ((count = read(in, buffer, sizeof buffer)) > 0)
{
send(out, buffer, count, 0);
}
if (count < 0)
{
perror("send failed");
}
I would avoid stdio for this, it has too many issues, such as the poorly designed fread() and fwrite() function APIs.
Other then the wrong size used in various places (as noted by mathematician1975), your "real" problem is that your trying to communicate with a browser that expects an HTTP server.
HyperText Transfer Protocol is, well, a protocol. It is more complex then a simple connection and a dump of content.
You have to parse the request according to it, and send headers and content in a certain way.
Check to see if bind() is failing and report if so. You're binding to port 80; under Unix-like operating systems only root can bind to reserved ports (less than 1024).
Update 1:
You must initialize addrlen to sizeof(address) before calling accept(). From http://linux.die.net/man/2/accept:
The addrlen argument is a value-result argument: the caller must
initialize it to contain the size (in bytes) of the structure pointed
to by addr; on return it will contain the actual size of the peer
address.
When sending a file through socket from client to server the file size changes. Where the problem may be?
Here is the client's side code:
char chunk[512];
host_info = gethostbyname(server);
if (host_info == NULL) {
perror("get host by name");
exit(errno);
}
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0) {
perror("socket");
exit(errno);
}
server_address.sin_family = host_info->h_addrtype;
memcpy((char *) &server_address.sin_addr.s_addr, host_info->h_addr_list[0], host_info->h_length);
server_address.sin_port = htons(PORT);
if (connect(socket_desc, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
perror("connect");
exit(errno);
}
file_to_send = fopen (lfile,"rb");
if(!file_to_send) {
perror("fopen");
close(socket_desc);
exit(errno);
} else {
long file_size;
fseek (file_to_send, 0, SEEK_END);
file_size = ftell (file_to_send);
rewind(file_to_send);
while(totally_read < file_size){
chunk[0] = '\0';
bytes_read = fread(chunk, sizeof(char), sizeof(chunk), file_to_send);
totally_read += bytes_read;
int sent = send(socket_desc, chunk, bytes_read, 0);
if(sent < 0){
perror("connect");
exit(errno);
}
totally_sent += sent;
printf("read: %7db sent: %7db totally read: %7db totally sent: %7db\n", bytes_read, sent, totally_read, totally_sent);
}
And here is the server side:
char chunk[512];
listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket < 0) {
perror("socket");
close(listen_socket);
exit(errno);
}
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(PORT);
if (bind(listen_socket, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
perror("bind");
close(listen_socket);
exit(errno);
}
listen(listen_socket, 5);
client_address_length = sizeof(client_address);
while(1){
connect_socket = accept(listen_socket, (struct sockaddr *) &client_address, &client_address_length);
if (connect_socket < 0) {
perror("accept");
close(listen_socket);
exit(errno);
}
recv_file = fopen(filename,"wb");
int received = 0;
int totally_wrote = 0, totally_received = 0;
while(1){
chunk[0] = '\0';
received = recv(connect_socket, chunk, sizeof(chunk), 0);
if(received < 0) {
perror("recv");
} else if(received > 0) {
int wrote = fwrite(chunk, sizeof(char), received, recv_file);
totally_wrote +=wrote;
totally_received += received;
printf("received: %7db wrote: %7db totally received: %7db torally wrote: %7db\n", received, wrote, totally_received, totally_wrote);
} else {
printf("Complete!\n");
break;
}
}
When sending a text file I get the following output
on the client side:
totally read: 299695b | totally sent: 299695b
but on the server side:
totally received: 303279b | torally wrote: 303279b
I've opened the file with the editor. The transmitted file is practically the same with the source file, except for some strange data in the beginning. The transmitted file 3584 bytes of additionsl binary data in the beginning if the chunk size is 512 bytes. It adds 3840 bytes if i change the chunk size to 256 bytes.
You are not checking the return value from send()
Send() can return any value between -1 and the third (length) argument, inclusive. You assume any return value > 0 to be equal to the 3rd argument. They need not be.
to deal with short send()s (or recv()s (or read() / write()) you'll need something like:
int sent, pos, bytes_read;
bytes_read = fread(chunk, sizeof(char), sizeof(chunk), file_to_send);
totally_read += bytes_read;
for (pos = 0; pos < bytes_read; pos += sent) {
sent = send(socket_desc, chunk+pos, bytes_read-pos, 0)
switch(sent) {
case -1: /* handle errno here, especially EAGAIN/EINTR */
case 0: /*handle EOF here */
break;
default:
break;
}
}
totally_sent += pos;
This is a snippet of client.c:
size_t fsize;
int total_bytes_read = 0, ret_val;
hp = gethostbyname(argv[1]);
DescrittoreClient = socket(AF_INET, SOCK_STREAM, 0);
connect(DescrittoreClient, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
strcpy(Buffer, filename);
send(DescrittoreClient, Buffer, strlen(Buffer), 0);
ret_val = read(DescrittoreClient, &fsize, sizeof(fsize));
if(ret_val == -1){
printf("Errore durante ricezione grandezza file\n");
close(DescrittoreClient);
exit(1);
}
fd = open(filename, O_CREAT | O_WRONLY,0644);
if (fd < 0) {
perror("open");
exit(1);
}
while(total_bytes_read < fsize){
while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){
write(fd, Buffer, nread);
total_bytes_read += nread;
}
}
printf("File ricevuto\n");
And this is a snippet of server.c:
int DescrittoreServer, DescrittoreClient, LunghezzaClient;
int NumPorta = atoi(argv[1]);
char Buffer[1024] = {};
int rc, fd;
off_t offset = 0;
struct stat stat_buf;
char filename[1024] = {};
int fsize[10240] = {};
DescrittoreServer = socket(AF_INET, SOCK_STREAM, 0);
if(bind(DescrittoreServer, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
perror("Errore di bind\n");
close(DescrittoreServer);
exit(1);
}
listen(DescrittoreServer, 5);
LunghezzaClient = sizeof(cli_addr);
while(1){
DescrittoreClient = accept(DescrittoreServer, (struct sockaddr *) &cli_addr, &LunghezzaClient);
rc = recv(DescrittoreClient, filename, sizeof(filename), 0);
fprintf(stderr, "Ricevuta richiesta di inviare il file: '%s'\n", filename);
/* open the file to be sent */
fd = open(filename, O_RDONLY);
/* get the size of the file to be sent */
fstat(fd, &stat_buf);
*fsize = stat_buf.st_size;
send(DescrittoreClient, fsize, sizeof(fsize), 0);
/* copy file using sendfile */
offset = 0;
rc = sendfile(DescrittoreClient, fd, &offset, stat_buf.st_size);
if (rc != stat_buf.st_size) {
fprintf(stderr, "Trasferimento incompleto: %d di %d bytes\n", rc, (int)stat_buf.st_size);
exit(1);
}
close(DescrittoreClient);
close(fd);
}
What does this code do:
1) client sends the name of a file
2) server sends the length (in byte) of the file
3) client receives the length of the file
4) server sends the file
5) client receives the file
The problem is that the file is not entirely received but only a part of it is written by the client (for example a file of 2143 byte is sent by the server and only 95 byte are received by the client) and i don't understand why!
PS: some errors handling have been deleted so the code is more readable!
You have to call recv() in a loop and sum up it's return values:
while (read_bytes < filesize) {
read_bytes += recv(socket, buffer + read_bytes, filesize-read_bytes, flags)
}
of course you should also add error handling, i.e., check if you read 0 bytes and the connection was closed.
The problem is that i have declared char nread=0 instead of int nread=0 into the client and so the maximum value i can read with char is 127...changed char to int solved my problem!