Linux write file to socket

Send and Receive a file in socket programming in Linux with C/C++ (GCC/G++)

I would like to implement a client-server architecture running on Linux using sockets and C/C++ language that is capable of sending and receiving files. Is there any library that makes this task easy? Could anyone please provide an example?

4 Answers 4

The most portable solution is just to read the file in chunks, and then write the data out to the socket, in a loop (and likewise, the other way around when receiving the file). You allocate a buffer, read into that buffer, and write from that buffer into your socket (you could also use send and recv , which are socket-specific ways of writing and reading data). The outline would look something like this:

while (1) < // Read data into buffer. We may not have enough to fill up buffer, so we // store how many bytes were actually read in bytes_read. int bytes_read = read(input_file, buffer, sizeof(buffer)); if (bytes_read == 0) // We're done reading from the file break; if (bytes_read < 0) < // handle errors >// You need a loop for the write, because not all of the data may be written // in one call; write will return how many bytes were written. p keeps // track of where in the buffer we are, while we decrement bytes_read // to keep track of how many bytes are left to write. void *p = buffer; while (bytes_read > 0) < int bytes_written = write(output_socket, p, bytes_read); if (bytes_written bytes_read -= bytes_written; p += bytes_written; > > 

Make sure to read the documentation for read and write carefully, especially when handling errors. Some of the error codes mean that you should just try again, for instance just looping again with a continue statement, while others mean something is broken and you need to stop.

For sending the file to a socket, there is a system call, sendfile that does just what you want. It tells the kernel to send a file from one file descriptor to another, and then the kernel can take care of the rest. There is a caveat that the source file descriptor must support mmap (as in, be an actual file, not a socket), and the destination must be a socket (so you can’t use it to copy files, or send data directly from one socket to another); it is designed to support the usage you describe, of sending a file to a socket. It doesn’t help with receiving the file, however; you would need to do the loop yourself for that. I cannot tell you why there is a sendfile call but no analogous recvfile .

Читайте также:  Coding python on linux

Beware that sendfile is Linux specific; it is not portable to other systems. Other systems frequently have their own version of sendfile , but the exact interface may vary (FreeBSD, Mac OS X, Solaris).

In Linux 2.6.17, the splice system call was introduced, and as of 2.6.23 is used internally to implement sendfile . splice is a more general purpose API than sendfile . For a good description of splice and tee , see the rather good explanation from Linus himself. He points out how using splice is basically just like the loop above, using read and write , except that the buffer is in the kernel, so the data doesn’t have to transferred between the kernel and user space, or may not even ever pass through the CPU (known as «zero-copy I/O»).

Источник

send file from client to server using socket in c on linux

I’m very new in C language and linux and English is not my mother language. Sorry for those in advance. What I need to is to send .avi or .mp4 files from a client to a server using socket on Linux. I can send the file from client to server but the video on the server is not working. When I try to play the video, I keep getting an error like «could not determine the type of stream». When I checked the original video on client, the size was 5,787,969 bytes but the size of the video transferred on server is 5,786,954 bytes. I think this is because of data loss when I transfer the file. How do I fix this? This is my code below:

Server

#include #include #include #include // read, write #include #include // socket, bind, accept, open #include // socket, bind, listen, accept #include // open #include // open #include #define PORT 5500 #define MAXBUF 1024 int main() < int server_sockfd; int client_sockfd; int des_fd; // file num struct sockaddr_in serveraddr, clientaddr; int client_len, read_len, file_read_len; // length char buf[MAXBUF]; int check_bind; client_len = sizeof(clientaddr); /* socket() */ server_sockfd = socket(AF_INET, SOCK_STREAM, 0); if(server_sockfd == -1) < perror("socket error : "); exit(0); >/* bind() */ bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(PORT); if(bind(server_sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) > 0) < perror("bind error : "); exit(0); >/* listen */ if(listen(server_sockfd, 5) != 0) < perror("listen error : "); >while(1) < char file_name[MAXBUF]; // local val memset(buf, 0x00, MAXBUF); /* accept() */ client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr, &client_len); printf("New Client Connect : %s\n", inet_ntoa(clientaddr.sin_addr)); /* file name */ read_len = read(client_sockfd, buf, MAXBUF); if(read_len >0) < strcpy(file_name, buf); printf("%s >%s\n", inet_ntoa(clientaddr.sin_addr), file_name); > else < close(client_sockfd); break; >/* create file */ des_fd = open(file_name, O_WRONLY | O_CREAT | O_EXCL, 0700); if(!des_fd) < perror("file open error : "); break; >/* file save */ while(1) < memset(buf, 0x00, MAXBUF); file_read_len = read(client_sockfd, buf, MAXBUF); write(des_fd, buf, file_read_len); if(file_read_len == EOF | file_read_len == 0) < printf("finish file\n"); break; >> close(client_sockfd); close(des_fd); > close(server_sockfd); return 0; > 

Client

#include #include #include #include #include #include #include #include #include #include #define PORT 5500 #define IP "127.0.0.1" #define MAXBUF 1024 int main() < struct sockaddr_in serv_addr; int s; int sourse_fd; char buf[MAXBUF]; int file_name_len, read_len; /* socket() */ s = socket(AF_INET, SOCK_STREAM, 0); if(s == -1) < return 1; >serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(IP); serv_addr.sin_port = htons(PORT); if(connect(s, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) < perror("connect : "); printf("fail to connect.\n"); close(s); return 1; >memset(buf, 0x00, MAXBUF); printf("write file name to send to the server: "); scanf("%s", buf); printf(" > %s\n", buf); file_name_len = strlen(buf); send(s, buf, file_name_len, 0); sourse_fd = open(buf, O_RDONLY); if(!sourse_fd) < perror("Error : "); return 1; >while(1) < memset(buf, 0x00, MAXBUF); read_len = read(sourse_fd, buf, MAXBUF); send(s, buf, read_len, 0); if(read_len == 0) < break; >> return 0; > 

Источник

Читайте также:  How to install graphics drivers on linux

How do I Write a .wav file on C++ using the socket layer in Linux?

I am trying to send wav files in C++ via TCP on Linux over a socket but I don’t understand how a wav file can be read correctly. My goal is to read the file on the client into a char array, send it with «write()» to the server, and the server should write the data into a local wav file again. I read the .wav file like this:

////////////define socket - left out for simplicity ifstream file ("audio.wav", ios::in|ios::binary|ios::ate); //open .wav file char * buffer; //declare data buffer, should contain .wav data to write to socket streampos filesize; //size of file int n; //number of written bytes //if file opened correctly, read content and write to socket if (file.is_open())

On the server, this returns the array «RIFF» of length «4», so its part of the header of the wav file. How can I read the whole .wav file content correctly for writing to the TCP socket? Thanks.

4 Answers 4

That is simple: filesize is size of the file in bytes. However, sizeof(buffer) is only 4 on a 32-bit OS. Modify your code like this:

To simplify processing on the other side, you may want to send filesize first to avoid parsing of the RIFF header to know how many bytes to accept. I would also suggest allocating a smaller buffer and reading several times to send the larger files over:

if(file.is_open()) < filesize = file.tellg(); file.seekg(0, ios::beg); uint32_t remains = filesize; write(socket, &remains, sizeof(uint32_t)); // write 4B with size of the file (optional) buffer = new char[(filesize >4096)? 4096 : filesize]; // only up to 4k buffer to avoid running out of memory n = 0; while(remains > 0) < int chunk = (remains >4096)? 4096 : remains; // decide how much to read in at one time (not more than size of the buffer) file.read(buffer, chunk); n += write_all(socket, buffer, chunk); // read a chunk and write it to the socket remains -= chunk; // update number of bytes that remains to be transferred > // send the file several times file.close(); delete[] buffer; // !! > 

You may notice the use of a helper function write_all . That is required, because the socket might get full and then write will not write all the data given to it. It could look like this:

size_t write_all(int socket, const char *buffer, size_t size) < size_t n = 0; while(size >0) < size_t written = write(socket, buffer, size); if(written == -1) return written; // handle errors n += written; size -= written; >return n; > 

Источник

Читайте также:  Linux mint install nouveau

Send a File with socket in C for Linux

I’m writing a small and simple server (in C language for Linux stations). A client requests a file to my server, my server asks this file to another server which sends it to my server. My server should NOT receive ALL the file before sending it to the client BUT must send the bytes of the file so as they arrive. This is an exercise in school so I can not dissociate myself from this requirement. I have implemented the function explained below. The problem is that the client receives a non-deterministic number of bytes and NEVER the entire file.

int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size) < size_t n; ssize_t nread; ssize_t nwritten; char c; for (n=1; nelse if (nread == 0) < *buffer = 0; return (-1); /* Errore */ >else return (-1); /* Errore */ > > *buffer = 0; return (n); > 

Someone could kindly tell me where I’m wrong? Is it an stupid idea to change the values ​​SO_SNDBUF and SO_RCVBUF on both the server and the client?

3 Answers 3

Assuming the file_size is the total number of bytes you want to send, then your for loop will only send file_size — 1 bytes. In other words, you are off by one. Start from 0 instead to fix this:

You capture the return value of send() , but you do not check to see if it was successful or not.

You are treating a 0 return value from recv() the same as an error. Since you do not show what you do after returning -1 from your function, I don’t know if this may be contributing to your problem or not.

Certain errors on send() and recv() are «soft», in that you are allowed to retry the operation for those particular errors. One such error is EINTR , but check the documentation on your system to see if there are others.

Источник

Оцените статью
Adblock
detector