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

Linux套接字编程:accept修改非指针参数fd的原因及解决办法

Socket descriptor fd gets overwritten to 0 causing "Socket operation on non-socket" error in accept()

Let's break down what's happening with your echo server and how to fix that frustrating socket error.

The Problem Recap

You've built a basic echo server, but after the first accept() call, your listening socket descriptor fd unexpectedly changes from 3 to 0. Subsequent loop iterations fail with accept: Socket operation on non-socket, and moving listen() into the loop didn't help.

Root Cause

Take a close look at your accept() call in the serve() function:

current_socket = accept(fd, (struct sockaddr*)&addr, (socklen_t*)&addrlen)

Here's the mistake: the second argument to accept() expects a pointer to a struct sockaddr (or struct sockaddr_in) where it can store the connecting client's address. But addr is already a pointer to struct sockaddr_in—by passing &addr, you're giving accept() a pointer to a pointer (struct sockaddr_in**), cast to struct sockaddr*.

When accept() tries to write the client's address data, it's writing into the wrong memory location. Since fd is the first parameter of the serve() function, followed by addr, the memory at &addr overlaps with the stack space holding fd. That's why fd gets clobbered to 0—accept() is corrupting its value by writing client address data where it shouldn't.

Fixes

You have two straightforward ways to resolve this:

1. Pass addr directly (simplest fix)

Since addr is already a valid pointer to a struct sockaddr_in, just cast it to struct sockaddr* without taking its address:

current_socket = accept(fd, (struct sockaddr*)addr, (socklen_t*)&addrlen)

2. Use a local client address variable (cleaner approach)

If you don't need to reuse the original addr parameter for client address storage, declare a local variable inside the loop. This eliminates any confusion with pointer levels:

while (true) {
    struct sockaddr_in client_addr;
    socklen_t client_addrlen = sizeof(client_addr);
    
    std::cout << "Fd before accept: " << fd << std::endl; 
    if ((current_socket = accept(fd, (struct sockaddr*)&client_addr, &client_addrlen)) < 0) { 
        std::perror("accept"); 
        exit(EXIT_FAILURE); 
    }
    
    // Rest of your connection handling code...
}

Bonus Improvements

While you're fixing this, here are two quick tweaks to make your server more robust:

  • Close client sockets: After sending the response to the client, call close(current_socket); to free up the file descriptor—leaving them open will cause resource leaks over time.
  • Null-terminate the input buffer: The read() system call doesn't add a null terminator to in_buf, which can lead to garbage characters when printing. Fix this right after reading:
    amount_read = read(current_socket, in_buf, 1024);
    if (amount_read > 0) {
        in_buf[amount_read] = '\0'; // Add null terminator
    } else if (amount_read == 0) {
        std::cout << "Client disconnected." << std::endl;
        close(current_socket);
        continue;
    } else {
        std::perror("read failed");
        close(current_socket);
        continue;
    }
    

内容的提问来源于stack exchange,提问作者Jacob Garby

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:09:10