如何用C语言读取可执行文件字符并基于Socket实现Linux下LAN文件传输?
Great question! Let's walk through how to finish your LAN file transfer tool—covering the core transfer logic, Linux right-click integration, and all the C implementation details you need.
You've already got the server waiting for connections and clients sending an initial 1024-byte message (with the first 4 bytes storing a length integer). Here's how to build out the rest of the flow:
1.1 Server-Side Implementation
Once a client connects, the server needs to parse the initial message, then receive and save the file data:
- Parse the initial packet: Extract the 4-byte length (convert from network byte order to host byte order with
ntohl()), then read the metadata (like filename and total file size) from the remaining bytes. - Prepare to receive the file: Create a local file with the parsed filename, then loop to receive chunks of data until you've collected the full file size.
- Confirm completion: Send a success signal back to the client once the file is saved.
Example code snippet for the server:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/stat.h> #include <fcntl.h> #define BUF_SIZE 4096 #define INIT_BUF_SIZE 1024 void handle_client(int client_fd) { char init_buf[INIT_BUF_SIZE] = {0}; ssize_t recv_len = recv(client_fd, init_buf, INIT_BUF_SIZE, 0); if (recv_len <= 0) { perror("Failed to receive initial message"); close(client_fd); return; } // Parse metadata length (network -> host byte order) uint32_t meta_len = ntohl(*(uint32_t*)init_buf); char meta[INIT_BUF_SIZE - 4] = {0}; strncpy(meta, init_buf + 4, meta_len); // Split metadata into filename and file size (format: "filename.txt:123456") char* filename = strtok(meta, ":"); uint64_t file_size = strtoull(strtok(NULL, ":"), NULL, 10); // Create and open the output file int file_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (file_fd == -1) { perror("Failed to open output file"); send(client_fd, "ERROR", 5, 0); close(client_fd); return; } // Receive file data in chunks char data_buf[BUF_SIZE] = {0}; uint64_t received_bytes = 0; while (received_bytes < file_size) { ssize_t bytes = recv(client_fd, data_buf, BUF_SIZE, 0); if (bytes <= 0) { perror("Failed to receive file data"); close(file_fd); close(client_fd); return; } write(file_fd, data_buf, bytes); received_bytes += bytes; } // Confirm success to client send(client_fd, "OK", 2, 0); close(file_fd); close(client_fd); }
1.2 Client-Side Implementation
The client needs to send the initial metadata packet, then stream the file data to the server:
- Prepare metadata: Combine the filename and file size into a string, calculate its length, and pack it into the 1024-byte initial buffer (with the first 4 bytes as the network-order length).
- Send metadata and wait for server confirmation: Once the server acknowledges it's ready, start reading the local file in chunks and sending them over the socket.
- Handle cleanup: Close the file and socket once transmission is complete.
Example code snippet for the client:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/stat.h> #include <fcntl.h> #include <libgen.h> #define BUF_SIZE 4096 #define INIT_BUF_SIZE 1024 int main(int argc, char* argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s <server_ip> <file_path>\n", argv[0]); return 1; } char* server_ip = argv[1]; char* file_path = argv[2]; // Create socket and connect to server int sock_fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_addr = {0}; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(12345); // Use your chosen port inet_pton(AF_INET, server_ip, &server_addr.sin_addr); if (connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) { perror("Failed to connect to server"); return 1; } // Get file size struct stat file_stat; if (stat(file_path, &file_stat) == -1) { perror("Failed to get file stats"); close(sock_fd); return 1; } uint64_t file_size = file_stat.st_size; // Prepare metadata packet char meta[INIT_BUF_SIZE - 4] = {0}; snprintf(meta, sizeof(meta), "%s:%llu", basename(file_path), file_size); uint32_t meta_len = strlen(meta); char init_buf[INIT_BUF_SIZE] = {0}; *(uint32_t*)init_buf = htonl(meta_len); strncpy(init_buf + 4, meta, meta_len); // Send initial metadata if (send(sock_fd, init_buf, INIT_BUF_SIZE, 0) == -1) { perror("Failed to send metadata"); close(sock_fd); return 1; } // Wait for server ready signal char ack[3] = {0}; if (recv(sock_fd, ack, sizeof(ack), 0) == -1 || strcmp(ack, "OK") != 0) { perror("Server not ready to receive"); close(sock_fd); return 1; } // Send file data int file_fd = open(file_path, O_RDONLY); if (file_fd == -1) { perror("Failed to open input file"); send(sock_fd, "ERROR", 5, 0); close(sock_fd); return 1; } char data_buf[BUF_SIZE] = {0}; ssize_t bytes_read; while ((bytes_read = read(file_fd, data_buf, BUF_SIZE)) > 0) { if (send(sock_fd, data_buf, bytes_read, 0) == -1) { perror("Failed to send file data"); close(file_fd); close(sock_fd); return 1; } } // Wait for final confirmation recv(sock_fd, ack, sizeof(ack), 0); close(file_fd); close(sock_fd); return 0; }
To add your tool to the right-click menu, the steps vary slightly depending on your desktop environment:
2.1 For GNOME (Nautilus)
- Create a scripts directory if it doesn't exist:
mkdir -p ~/.local/share/nautilus/scripts/ - Create a script file (e.g.,
Send via LAN Transfer):#!/bin/bash # Replace with your client executable path and server IP /path/to/your/client_executable 192.168.1.100 "$1" - Make the script executable:
chmod +x ~/.local/share/nautilus/scripts/Send\ via\ LAN\ Transfer - Restart Nautilus to apply changes:
nautilus -q
You’ll now see the option under the Scripts submenu when right-clicking a file.
2.2 For KDE (Dolphin)
- Create a service menu
.desktopfile:mkdir -p ~/.local/share/kservices5/ServiceMenus/ nano ~/.local/share/kservices5/ServiceMenus/lan-transfer.desktop - Paste this content (update paths and server IP):
[Desktop Entry] Type=Service ServiceTypes=KonqPopupMenu/Plugin MimeType=application/octet-stream;inode/directory; Actions=lanTransfer; [Desktop Action lanTransfer] Name=Send via LAN Transfer Exec=/path/to/your/client_executable 192.168.1.100 "%u" Icon=network-transmit - Restart Dolphin, and the option will appear in the right-click menu.
- Byte Order: Always use
htonl()/ntohl()to handle endianness differences between machines—this prevents garbled length values. - Large Files: Use
uint64_tfor file sizes to support files larger than 4GB. - Error Handling: Add checks for every socket and file operation to handle dropped connections or missing files gracefully.
- Security: Bind your server to your LAN IP (not
0.0.0.0) and consider adding a simple password check to prevent unauthorized transfers. - Progress Feedback: Add a progress bar in the client (using
printfto update the percentage) to give users visibility into transfer status.
内容的提问来源于stack exchange,提问作者Thomas Migus

