注册

Linux报 “socket operation on non-socket” 异常的原因以及解决办法

socket operation on non-socket这个错误通常出现在Linux系统中,主要是由于程序在对一个非socket文件描述符进行了套接字操作所导致的。这个错误提示通常会出现在网络编程中,比如使用非socket类型的文件描述符调用网络库函数,或者是使用了已经被关闭的socket文件描述符调用网络库函数。

造成socket operation on non-socket错误的原因可能有下面几个:

1.在调用socket相关函数前,没有初始化socket库,或初始化失败。

2.在关闭socket描述符使用shutdown函数后,继续对该socket文件描述符进行操作。

3.使用了一个根本不是socket描述符的文件描述符调用网络库函数。

以下是一些具体的示例:

1.没有初始化socket库

//Example 1:
#include 
#include 
#include 
#include 

// 没有初始化socket库,调用socket函数
int main(void)
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    close(fd);
    return 0;
}

在这个例子中,socket库没有被初始化,导致调用socket函数失败。需要先调用inet_pton函数进行socket库的初始化。

2.使用了已关闭的socket文件描述符

//Example 2:
#include 
#include 
#include 
#include 
#include 

int main(void)
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    close(fd);

    // 使用了已经关闭的socket文件描述符调用网络库函数
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    return 0;
}

在这个例子中,调用了已经关闭的fd文件描述符调用网络库函数,导致出现socket operation on non-socket的错误提示。需要在调用网络库函数前,检查fd是否已关闭。

3.使用了非socket描述符

//Example 3:
#include 
#include 
#include 
#include 

int main(void)
{
    // 使用了非socket描述符,调用listen函数
    int fd = open("/dev/zero", O_RDONLY);
    if (fd < 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    if (listen(fd, 5) < 0) { //调用listen函数
        perror("listen");
        exit(EXIT_FAILURE);
    }

    close(fd);
    return 0;
}

在这个例子中,一个非socket描述符被传递给listen函数,导致出现socket operation on non-socket的错误提示。

解决上述问题的方法:

1.在使用socket相关函数前,先初始化socket库。

2.在关闭socket描述符时,将描述符从epoll中删除,并保证不会再对该socket文件描述符进行操作。

3.在使用文件描述符调用网络库函数前,先检查该描述符是否为已打开的socket描述符。

正确的socket库初始化方法:

//正确的socket库初始化方法
#include 
#include 
#include 
#include 

int main(void)
{
    //正确的初始化socket库
    int ret = system("cat /dev/null > /dev/tcp/127.0.0.1/80");
    if (ret != 0) {
        perror("init socket");
        exit(EXIT_FAILURE);
    }

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    close(fd);
    return 0;
}

以上是关于Linux报socket operation on non-socket的原因与解决办法的介绍和示例。希望对您有所帮助。