简体   繁体   中英

accept socket errno 9 c++

New to socket programming, trying to implement a TCP server, but accept() returns -1 and errno = 9 (bad file descriptor). The problem arose after I introduced the accept() function in the freertos task. I really don't understand what the problem is here, because before this my action everything worked, but I need to use the task.

#include "TCP.hpp"
#include <iostream>
#include <cmath>
#include <cerrno>
#include <cstring>
#include <clocale>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "freertos/queue.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "ping/ping_sock.h"

#include "errno.h"

static const char *TAG = "TCP";

QueueHandle_t TCP::xQueue1 = NULL;
ip_addr_t TCP::target_addr;
int TCP::ip_protocol;
int TCP::listen_sock;
sockaddr_in TCP::servaddr; 
sockaddr_in TCP::cliaddr;
char TCP::addr_str[128];
char TCP::buf[128];
int TCP::sock;
TCP::Clbk_t TCP::clbk_tcp_recv = nullptr;
sockaddr_storage TCP::source_addr;

typedef struct 
{
    int len;
    void * dataPtr;
}message;

void TCP::tcp_set_Clbk(Clbk_t clbk)
{
    clbk_tcp_recv = clbk;
}

void TCP::tcp_create_server(sa_family_t serv_family, in_addr_t serv_addr, in_port_t serv_port)
{   
    int opt = 1;
    struct sockaddr_in6 *servaddrPtr;
    if (serv_family == AF_INET){
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_len = 24;
        servaddr.sin_family = serv_family;
        servaddr.sin_addr.s_addr = serv_addr;
        servaddr.sin_port = htons(serv_port);
        ip_protocol = IPPROTO_IP;    
    } else if (serv_family == AF_INET6){
        servaddrPtr = (struct sockaddr_in6 *)&servaddr;
        servaddrPtr->sin6_len = 24;
        servaddrPtr->sin6_family = serv_family;
        servaddrPtr->sin6_port = htons(serv_port);
        ip_protocol = IPPROTO_IPV6;
    }
    ESP_LOGI(TAG, "Create socket...\n");
    if ((listen_sock = socket(serv_family, SOCK_STREAM, ip_protocol)) < 0) {
        ESP_LOGE(TAG, "socket not created\n");
    }       
    setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    ESP_LOGI(TAG, "Socket created");

    int err = bind(listen_sock, (struct sockaddr *)&servaddr, sizeof(servaddr));
    if (err != 0) {
        ESP_LOGE(TAG, "Socket unable to bind errno %d", errno);
        ESP_LOGE(TAG, "IPPROTO: %d", serv_family);
        goto CLEAN_UP;
    }
    ESP_LOGI(TAG, "Socket bound, port %d", serv_port);

    err = listen(listen_sock, 1);
    if (err != 0) {
        ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
        goto CLEAN_UP;
    }

    ESP_LOGI(TAG, "Soccket listening . . .");

    xTaskCreate(tcp_listening_task, "tcp_listening_task", 4096, nullptr, 5, nullptr);   


CLEAN_UP:
    close(listen_sock);
}

void TCP::tcp_listening_task(void *arg)
{
    int keepAlive = 1;
    socklen_t addr_len = sizeof(source_addr);
    ESP_LOGI(TAG, "Socket %d ",listen_sock);
    for (;;) {
        sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
        ESP_LOGI(TAG, "Socket %d ",sock);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
        }
        
        if (sock > 0) {
            setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));

            if (source_addr.ss_family == PF_INET) {
                inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
            }
            else if (source_addr.ss_family == PF_INET6) {
                inet6_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
            }

            ESP_LOGI(TAG, "Socket %d accepted ip address: %s",sock, addr_str);
            xTaskCreate(tcp_task_recv, "tcp_task_recv", 4096, nullptr, 5, nullptr);
        }

    }

}

void TCP::tcp_task_recv(void *arg)
{
    int n;
    int number_receiving = 0;
    struct timeval tv;
    tv.tv_sec = 1;  
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval));
    ESP_LOGI(TAG,"server waiting message");
    for (;;) {
        n = recv(sock, (char *)buf, sizeof(buf), 0);
        if (n < 0) {
            ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno);
            number_receiving++;
            if (number_receiving == 10) {
                number_receiving = 0;
            }
        }
        else if (n == 0) {
            ESP_LOGW(TAG, "Connection closed");
            number_receiving = 0;
        }
        else {
            if (clbk_tcp_recv != nullptr) clbk_tcp_recv(buf, n, (struct sockaddr *)&source_addr);
            number_receiving = 0;
        }
    }
}

void TCP::tcp_sendd(void *data, uint32_t length)
{
    static message msg;
    xQueue1 = xQueueCreate(10, sizeof(message));
    xTaskCreate(tcp_task_send, "udp_task_send", 4096, nullptr, 5, nullptr);

    if(sock < 0){
        ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
        return;
    }
    if(xQueue1 == NULL){
        ESP_LOGE(TAG, "queue is null");
        return;
    }
    msg.dataPtr = data;
    msg.len = length;
    xQueueSend(xQueue1, (void *)&msg, portMAX_DELAY);
}

void TCP::tcp_task_send(void *arg)
{   
    message pxRxedMessage;
    for(;;)
    {
        xQueueReceive(xQueue1, (void *)&pxRxedMessage, portMAX_DELAY);
        int err = send(sock, pxRxedMessage.dataPtr, pxRxedMessage.len, 0);
        if (err < 0){
            ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
        } 
    }
}

I tried to look for information on this issue, but since. I'm also new to c++ programming, nothing worked out

You should be passing the listen_sock as the arg parameter to tcp_listening_task() , rather than using a static class member, eg:

int listen_sock = socket(...);
...
xTaskCreate(tcp_listening_task, "tcp_listening_task", 4096, reinterpret_cast<void*>(listen_sock), 5, nullptr);

...

void TCP::tcp_listening_task(void *arg)
{
    int listen_sock = reinterpret_cast<int>(arg);
    ...
    close(listen_sock);
}

And especially the same with sock and tcp_task_recv() too, since your server is designed to handle multiple clients being connected simultaneously, which you can't handle with a single static sock variable:

int sock = accept(...);
...
xTaskCreate(tcp_task_recv, "tcp_task_recv", 4096, reinterpret_cast<void*>(sock), 5, nullptr);

...

void TCP::tcp_task_recv(void *arg)
{
    int sock = reinterpret_cast<int>(arg);
    ...
    close(sock);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM