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

简易Socket程序在Ubuntu WSL中调用accept()失败,errno=22

跨平台Socket服务端accept()错误排查(错误码22)

问题描述

在Ubuntu WSL环境运行以下跨平台Socket服务端代码时,程序执行到accept()步骤失败,错误码为22。已排查端口8080未被占用、使用sudo运行程序、关闭防火墙及网络防护工具,但问题仍未解决。

服务端代码

#if defined (_WIN32)
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
#define ISVALIDSOCKET(s) ((s) != INVALID_SOCKET)
#define CLOSESOCKET(s) closesocket(s)
#define GETSOCKETERRNO() (WSAGetLastError())
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define ISVALIDSOCKET(s) ((s) >= 0)
#define CLOSESOCKET(s) close(s)
#define SOCKET int
#define GETSOCKETERRNO() (errno)
#endif


int main(void)
{
        printf("Configuring local address ...\n");
        struct addrinfo hints;
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;

        struct addrinfo *bind_address;
        getaddrinfo(0, "8080", &hints, &bind_address);

        printf("Creating socket...\n");
        SOCKET socket_listen;
        socket_listen = socket(bind_address->ai_family, bind_address->ai_socktype, bind_address->ai_protocol);

        if (!ISVALIDSOCKET(socket_listen))
        {
                fprintf(stderr, "socket() failed. (%d)", GETSOCKETERRNO());
                return 1;
        }

        printf("Binding socket to local address...\n");
        if (bind(socket_listen, bind_address->ai_addr, bind_address->ai_addrlen))
        {
                fprintf(stderr, "bind() failed. (%d)\n", GETSOCKETERRNO());
                return 1;
        }
        freeaddrinfo(bind_address);

        printf("Waiting for connection...\n");
        struct sockaddr_storage client_address;
        socklen_t client_len = sizeof(client_address);
        printf("running the accept function\n");
        SOCKET socket_client = accept(socket_listen, (struct sockaddr*) &client_address, &client_len);
        if (!ISVALIDSOCKET(socket_client))

        {
                fprintf(stderr, "accept() failed. (%d)\n",GETSOCKETERRNO());
                return 1;
        }

        printf("Client is connected...");
        char address_buffer[100];
        getnameinfo((struct sockaddr*)&client_address, client_len, address_buffer, sizeof(address_buffer), 0, 0, NI_NUMERICHOST);
        printf("%s\n", address_buffer);


        printf("Reading request...\n");
        char request [1024];
        int bytes_recieved = recv(socket_client, request, 1024,0 );
        printf("Recieved %d bytes .\n", bytes_recieved);
        printf("%.*s", bytes_recieved,request);


        printf("Sending response...\n");
        const char *response =
                "HTTP/1.1 200 OK\r\n"
                "Connection: close:\r\n"
                "Content-Type: text/plain\r\n\r\n"
                "Local time is: ";
        int bytes_sent = send(socket_client, response, strlen(response), 0);
        printf("Send %d of %d bytes.\n", bytes_sent, (int)strlen(response));


        time_t timer;
        time (&timer);
        char *time_msg = ctime(&timer);
        bytes_sent = (socket_client, time_msg, strlen(time_msg), 0);
        printf("Send %d of %d bytes.\n", bytes_sent, (int)strlen(time_msg));



        printf("Closing connection...\n");
        CLOSESOCKET(socket_client);


        printf("Closing listening socket...\n");
        CLOSESOCKET(socket_listen);


#if defined(_WIN32)
        WSACleanup();
#endif
        printf("Finished.\n");

        return 0;

}

错误现象

程序运行输出如下后终止:

Configuring local address ...
Creating socket...
Binding socket to local address...
Waiting for connection...
accept() failed. (22)

原因分析

错误码22对应Linux下的EINVAL,触发该错误的核心原因是:监听套接字未调用listen()函数就直接执行accept()。TCP套接字的正确流程是socket() -> bind() -> listen() -> accept(),缺少listen()会导致accept()参数无效,返回EINVAL。

另外代码中还有一处语法错误:发送时间字符串的语句缺少send关键字,会导致编译警告或运行时错误。

解决方法

  1. 在bind()完成后、accept()之前添加listen()调用:

    printf("Listening on socket...\n");
    if (listen(socket_listen, 10) < 0) {
        fprintf(stderr, "listen() failed. (%d)\n", GETSOCKETERRNO());
        return 1;
    }
    

    第二个参数10是监听队列的最大长度,可根据需求调整。

  2. 修复发送时间字符串的语法错误,补全send关键字:

    bytes_sent = send(socket_client, time_msg, strlen(time_msg), 0);
    

修改后的完整代码可正常在Ubuntu WSL环境运行,等待客户端连接并响应请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 05:35:17