You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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.

1. Complete the Core File Transfer Logic

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;
}
2. Integrate with Linux Right-Click Menu

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 .desktop file:
    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.
3. Critical Edge Cases & Improvements
  • Byte Order: Always use htonl()/ntohl() to handle endianness differences between machines—this prevents garbled length values.
  • Large Files: Use uint64_t for 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 printf to update the percentage) to give users visibility into transfer status.

内容的提问来源于stack exchange,提问作者Thomas Migus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:59:03