Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Final Project Simple File Server | Advanced Networking Techniques
Practice
Projects
Quizzes & Challenges
Quizzes
Challenges
/
C Networking Basics

bookFinal Project Simple File Server

For your final project, you will create a simple file server and client in C. This project will bring together the networking concepts you have learned so far, including sockets, protocol design, and file transfer. The server will serve files from a specified directory. When a client connects, the server will send a list of available files. The client can request a file by name, and the server will send the file's contents back for the client to save locally.

Your project requirements are as follows:

  • The server must listen for incoming connections on a specified port;
  • When a client connects, the server must send a list of available files in its directory;
  • The client must display this list and allow the user to select a file to download;
  • The client sends the file name to the server, which then sends the file's contents;
  • The client saves the received file locally;
  • Both server and client should handle errors, such as file not found or connection issues.

The design plan is straightforward:

  1. Start the server, which scans its directory for files and waits for a client connection;
  2. When a client connects, send the list of files, separated by newlines;
  3. The client receives and displays this list, then prompts the user for a filename;
  4. The client sends the filename to the server;
  5. The server checks if the file exists. If yes, it sends the file size, then the file contents. If not, it sends an error message;
  6. The client receives the file (or error message) and saves it, displaying appropriate messages for success or failure.

This step-by-step plan ensures a clear protocol and robust error handling, while reinforcing your understanding of sockets, file I/O, and communication patterns.

server.c

server.c

client.c

client.c

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/stat.h> #include <errno.h> #define PORT 9000 #define BUF_SIZE 1024 #define FILE_DIR "./files" void send_file_list(int client_sock) { DIR *d; struct dirent *dir; char list[BUF_SIZE] = ""; d = opendir(FILE_DIR); if (d) { while ((dir = readdir(d)) != NULL) { if (dir->d_type == DT_REG) { strcat(list, dir->d_name); strcat(list, "\n"); } } closedir(d); } send(client_sock, list, strlen(list), 0); } void send_file(int client_sock, const char *filename) { char filepath[512]; snprintf(filepath, sizeof(filepath), "%s/%s", FILE_DIR, filename); FILE *fp = fopen(filepath, "rb"); if (!fp) { char *err = "ERROR: File not found\n"; send(client_sock, err, strlen(err), 0); return; } fseek(fp, 0, SEEK_END); long filesize = ftell(fp); fseek(fp, 0, SEEK_SET); char header[64]; snprintf(header, sizeof(header), "OK %ld\n", filesize); send(client_sock, header, strlen(header), 0); char buf[BUF_SIZE]; size_t n; while ((n = fread(buf, 1, BUF_SIZE, fp)) > 0) { if (send(client_sock, buf, n, 0) != n) { break; } } fclose(fp); } int main() { int server_fd, client_sock; struct sockaddr_in server_addr, client_addr; socklen_t addr_len = sizeof(client_addr); mkdir(FILE_DIR, 0777); // ensure directory exists server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { perror("socket"); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("bind"); close(server_fd); exit(1); } if (listen(server_fd, 5) < 0) { perror("listen"); close(server_fd); exit(1); } printf("File server listening on port %d...\n", PORT); while (1) { client_sock = accept(server_fd, (struct sockaddr *)&client_addr, &addr_len); if (client_sock < 0) { perror("accept"); continue; } printf("Client connected: %s\n", inet_ntoa(client_addr.sin_addr)); send_file_list(client_sock); char filename[256] = {0}; int len = recv(client_sock, filename, sizeof(filename) - 1, 0); if (len > 0) { filename[strcspn(filename, "\r\n")] = 0; // remove newline send_file(client_sock, filename); } close(client_sock); printf("Client disconnected.\n"); } close(server_fd); return 0; }
question mark

In a simple file server, what is the purpose of sending a list of available files to the client?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 3. ChapterΒ 4

Ask AI

expand

Ask AI

ChatGPT

Ask anything or try one of the suggested questions to begin our chat

Suggested prompts:

Can you provide example code for the server and client?

What are some common errors I should watch out for in this project?

Can you explain how to handle file not found errors in the protocol?

bookFinal Project Simple File Server

Swipe to show menu

For your final project, you will create a simple file server and client in C. This project will bring together the networking concepts you have learned so far, including sockets, protocol design, and file transfer. The server will serve files from a specified directory. When a client connects, the server will send a list of available files. The client can request a file by name, and the server will send the file's contents back for the client to save locally.

Your project requirements are as follows:

  • The server must listen for incoming connections on a specified port;
  • When a client connects, the server must send a list of available files in its directory;
  • The client must display this list and allow the user to select a file to download;
  • The client sends the file name to the server, which then sends the file's contents;
  • The client saves the received file locally;
  • Both server and client should handle errors, such as file not found or connection issues.

The design plan is straightforward:

  1. Start the server, which scans its directory for files and waits for a client connection;
  2. When a client connects, send the list of files, separated by newlines;
  3. The client receives and displays this list, then prompts the user for a filename;
  4. The client sends the filename to the server;
  5. The server checks if the file exists. If yes, it sends the file size, then the file contents. If not, it sends an error message;
  6. The client receives the file (or error message) and saves it, displaying appropriate messages for success or failure.

This step-by-step plan ensures a clear protocol and robust error handling, while reinforcing your understanding of sockets, file I/O, and communication patterns.

server.c

server.c

client.c

client.c

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/stat.h> #include <errno.h> #define PORT 9000 #define BUF_SIZE 1024 #define FILE_DIR "./files" void send_file_list(int client_sock) { DIR *d; struct dirent *dir; char list[BUF_SIZE] = ""; d = opendir(FILE_DIR); if (d) { while ((dir = readdir(d)) != NULL) { if (dir->d_type == DT_REG) { strcat(list, dir->d_name); strcat(list, "\n"); } } closedir(d); } send(client_sock, list, strlen(list), 0); } void send_file(int client_sock, const char *filename) { char filepath[512]; snprintf(filepath, sizeof(filepath), "%s/%s", FILE_DIR, filename); FILE *fp = fopen(filepath, "rb"); if (!fp) { char *err = "ERROR: File not found\n"; send(client_sock, err, strlen(err), 0); return; } fseek(fp, 0, SEEK_END); long filesize = ftell(fp); fseek(fp, 0, SEEK_SET); char header[64]; snprintf(header, sizeof(header), "OK %ld\n", filesize); send(client_sock, header, strlen(header), 0); char buf[BUF_SIZE]; size_t n; while ((n = fread(buf, 1, BUF_SIZE, fp)) > 0) { if (send(client_sock, buf, n, 0) != n) { break; } } fclose(fp); } int main() { int server_fd, client_sock; struct sockaddr_in server_addr, client_addr; socklen_t addr_len = sizeof(client_addr); mkdir(FILE_DIR, 0777); // ensure directory exists server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { perror("socket"); exit(1); } server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("bind"); close(server_fd); exit(1); } if (listen(server_fd, 5) < 0) { perror("listen"); close(server_fd); exit(1); } printf("File server listening on port %d...\n", PORT); while (1) { client_sock = accept(server_fd, (struct sockaddr *)&client_addr, &addr_len); if (client_sock < 0) { perror("accept"); continue; } printf("Client connected: %s\n", inet_ntoa(client_addr.sin_addr)); send_file_list(client_sock); char filename[256] = {0}; int len = recv(client_sock, filename, sizeof(filename) - 1, 0); if (len > 0) { filename[strcspn(filename, "\r\n")] = 0; // remove newline send_file(client_sock, filename); } close(client_sock); printf("Client disconnected.\n"); } close(server_fd); return 0; }
question mark

In a simple file server, what is the purpose of sending a list of available files to the client?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

SectionΒ 3. ChapterΒ 4
some-alt