21 Star 71 Fork 20

OpenHarmony / vendor_hisi_hi3861_hi3861

TCP服务端accept失败,errno=12 ENOMEM /* Out of memory */

Task
Done
许思维  Opened this issue

同样的TCP服务端代码,在Linux服务器上可以测试通过,在Hi3861上accept失败,errno = 12;
是lwip编译时候配置的内存小了吗?

===============================================================
测试代码如下:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#if defined(__linux__)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#else // __linux__
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_device.h"

#include "lwip/sockets.h"
#include "lwip/netifapi.h"
#include "lwip/api_shell.h"

#define close(fd) lwip_close(fd)

#define PARAM_HOTSPOT_SSID "ABCD"   // your AP SSID
#define PARAM_HOTSPOT_PSK  "12345678"  // your AP PSK
#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK // defined in wifi_device_config.h

#endif // __linux__

#define PARAM_SERVER_PORT 5678

static char request[128] = "";
static ssize_t TcpServerTest(unsigned short port)
{
    ssize_t retval = 0;
    int backlog = 1;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
    int connfd = -1;

    socklen_t clientAddrLen = 0;
    struct sockaddr_in clientAddr = {0};
    struct sockaddr_in serverAddr = {0};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    retval = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
    if (retval < 0) {
        printf("bind failed, %ld!\r\n", retval);
        goto do_cleanup;
    }
    printf("bind to port %d success!\r\n", port);

    retval = listen(sockfd, backlog);
    if (retval < 0) {
        printf("listen failed!\r\n");
        goto do_cleanup;
    }
    printf("listen with %d backlog success!\r\n", backlog);

    connfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen);
    if (connfd < 0) {
        printf("accept failed, %d, %d\r\n", connfd, errno);
        goto do_cleanup;
    }
    printf("accept success, connfd = %d!\r\n", connfd);

    retval = recv(connfd, request, sizeof(request), 0);
    if (retval < 0) {
        printf("recv request failed, %ld!\r\n", retval);
        goto do_disconnect;
    }
    printf("recv request{%s} from client done!\r\n", request);

    retval = send(connfd, request, strlen(request), 0);
    if (retval <= 0) {
        printf("send response failed, %ld!\r\n", retval);
        goto do_disconnect;
    }
    printf("send response{%s} to client done!\r\n", request);

do_disconnect:
    sleep(1);
    close(connfd);
    sleep(1); // for debug

do_cleanup:
    printf("do_cleanup...\r\n");

    close(sockfd);
    return retval;
}

#if defined(__linux__)
int main(int argc, char* argv[])
{
    unsigned short port = argc > 1 ? atoi(argv[1]) : PARAM_SERVER_PORT;
    TcpServerTest(port);
    return 0;
}
#else // __linux__

static void PrintLinkedInfo(WifiLinkedInfo* info)
{
    if (!info) return;

    static char macAddress[32] = {0};
    unsigned char* mac = info->bssid;
    snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n",
        macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid);
}

static volatile int g_connected = 0;

static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
{
    if (!info) return;

    printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state);
    PrintLinkedInfo(info);

    if (state == WIFI_STATE_AVALIABLE) {
        g_connected = 1;
    } else {
        g_connected = 0;
    }
}

static void OnWifiScanStateChanged(int state, int size)
{
    printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size);
}

static WifiEvent g_defaultWifiEventListener = {
    .OnWifiConnectionChanged = OnWifiConnectionChanged,
    .OnWifiScanStateChanged = OnWifiScanStateChanged
};

static struct netif* g_iface = NULL;

int ConnectToHotspot(WifiDeviceConfig* apConfig)
{
    WifiErrorCode errCode;
    int netId = -1;

    errCode = RegisterWifiEvent(&g_defaultWifiEventListener);
    printf("RegisterWifiEvent: %d\r\n", errCode);

    errCode = EnableWifi();
    printf("EnableWifi: %d\r\n", errCode);

    errCode = AddDeviceConfig(apConfig, &netId);
    printf("AddDeviceConfig: %d\r\n", errCode);

    g_connected = 0;
    errCode = ConnectTo(netId);
    printf("ConnectTo(%d): %d\r\n", netId, errCode);

    while (!g_connected) { // wait until connect to AP
        osDelay(10);
    }
    printf("g_connected: %d\r\n", g_connected);

    g_iface = netifapi_netif_find("wlan0");
    if (g_iface) {
        err_t ret = netifapi_dhcp_start(g_iface);
        printf("netifapi_dhcp_start: %d\r\n", ret);

        osDelay(100); // wait DHCP server give me IP
        ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL);
        printf("netifapi_netif_common: %d\r\n", ret);
    }
    return netId;
}

void DisconnectWithHotspot(int netId)
{
    if (g_iface) {
        err_t ret = netifapi_dhcp_stop(g_iface);
        printf("netifapi_dhcp_stop: %d\r\n", ret);
    }

    WifiErrorCode errCode = Disconnect(); // disconnect with your AP
    printf("Disconnect: %d\r\n", errCode);

    errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener);
    printf("UnRegisterWifiEvent: %d\r\n", errCode);

    RemoveDevice(netId); // remove AP config
    printf("RemoveDevice: %d\r\n", errCode);

    errCode = DisableWifi();
    printf("DisableWifi: %d\r\n", errCode);
}

static void TcpServerTask(void *arg)
{
    (void)arg;
    WifiDeviceConfig config = {0};

    // 准备AP的配置参数
    strcpy(config.ssid, PARAM_HOTSPOT_SSID);
    strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
    config.securityType = PARAM_HOTSPOT_TYPE;

    osDelay(10);
    int netId = ConnectToHotspot(&config);

    int timeout = 10;
    while (timeout--) {
        printf("After %d seconds, I will start TCP server test!\r\n", timeout);
        osDelay(100);
    }

    TcpServerTest(PARAM_SERVER_PORT);

    printf("disconnect to AP ...\r\n");
    DisconnectWithHotspot(netId);
    printf("disconnect to AP done!\r\n");
}

static void TcpServerDemo(void)
{
    osThreadAttr_t attr;

    attr.name = "TcpServerTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 4096;
    attr.priority = osPriorityNormal;

    if (osThreadNew(TcpServerTask, NULL, &attr) == NULL) {
        printf("[TcpServerDemo] Falied to create TcpServerTask!\n");
    }
}

SYS_RUN(TcpServerDemo);
#endif // __linux__

===============================================================
Linux上编译:

gcc tcp_srever_test.c

Linux上运行服务端:

./a.out

Linux上运行客户端,可以成功连接上服务端:

$ nc localhost 5678
asdf
asdf

===============================================================
Hi3861开发版上运行结果:


[23:29:37.181]收←◆ready to OS start
sdk ver:Hi3861V100R001C00SPC025 2020-09-03 18:10:00
formatting spiffs...

[23:29:37.528]收←◆FileSystem mount ok.
wifi init success!

00 00:00:00 0 68 D 0/HIVIEW: hilog init success.
00 00:00:00 0 68 D 0/HIVIEW: log limit init success.
00 00:00:00 0 68 I 1/SAMGR: Bootstrap core services(count:3).
00 00:00:00 0 68 I 1/SAMGR: Init service:0x4af8c8 TaskPool:0xfb7c8
00 00:00:00 0 68 I 1/SAMGR: Init service:0x4af8ec TaskPool:0xfbe38
00 00:00:00 0 68 I 1/SAMGR: Init service:0x4af9fc TaskPool:0xfbff8
00 00:00:00 0 200 I 1/SAMGR: Init service 0x4af8ec <time: 0ms> success!
00 00:00:00 0 100 I 1/SAMGR: Init service 0x4af8c8 <time: 0ms> success!
00 00:00:00 0 44 D 0/HIVIEW: hiview init success.
00 00:00:00 0 44 I 1/SAMGR: Init service 0x4af9fc <time: 0ms> success!
00 00:00:00 0 44 I 1/SAMGR: Initialized all core system services!
00 00:00:00 0 100 I 1/SAMGR: Bootstrap system and application services(count:0).
00 00:00:00 0 100 I 1/SAMGR: Initialized all system and application services!
00 00:00:00 0 100 I 1/SAMGR: Bootstrap dynamic registered services(count:0).

[23:29:37.706]收←◆RegisterWifiEvent: 0
EnableWifi: 0
AddDeviceConfig: 0

[23:29:38.138]收←◆ConnectTo(0): 0

[23:29:38.911]收←◆+NOTICE:SCANFINISH
+NOTICE:CONNECTED
OnWifiConnectionChanged 120, state = 1, info = 
bssid: 70:C9:4E:E3:00:4B, rssi: 0, connState: 0, reason: 0, ssid: ABCD

[23:29:39.030]收←◆g_connected: 1
netifapi_dhcp_start: 0

[23:29:40.031]收←◆server :
	server_id : 192.168.137.1
	mask : 255.255.255.0, 1
	gw : 192.168.137.1
	T0 : 604800
	T1 : 300
	T2 : 453600
clients <1> :
	mac_idx mac             addr            state   lease   tries   rto     
	0       b4c9b9af6903    192.168.137.56  10      0       1       4       
netifapi_netif_common: 0
After 9 seconds, I will start TCP server test!

[23:29:41.051]收←◆After 8 seconds, I will start TCP server test!

[23:29:42.050]收←◆After 7 seconds, I will start TCP server test!

[23:29:43.050]收←◆After 6 seconds, I will start TCP server test!

[23:29:44.050]收←◆After 5 seconds, I will start TCP server test!

[23:29:45.050]收←◆After 4 seconds, I will start TCP server test!

[23:29:46.051]收←◆After 3 seconds, I will start TCP server test!

[23:29:47.050]收←◆After 2 seconds, I will start TCP server test!

[23:29:48.050]收←◆After 1 seconds, I will start TCP server test!

[23:29:49.050]收←◆After 0 seconds, I will start TCP server test!

[23:29:50.051]收←◆bind to port 5678 success!
listen with 1 backlog success!

[23:29:53.805]发→◇AT+SYSINFO
□
[23:29:53.810]收←◆AT+SYSINFO
+SYSINFO:
mem:
total=211264,used=81212,free=130052,peek_size=86020
os_resource:
timer_usage=15,task_usage=12,sem_usage=7,queue_usage=4,mux_usage=21,event_usage=3
task_info:
Swt_Task,id=0,status=8192,pri=0,size=0x800,cur_size=0x100,peak_size=0x174
IdleCore000,id=1,status=4,pri=31,size=0x400,cur_size=0xb0,peak_size=0x124
wpa_supplicant,id=2,status=8,pri=4,size=0x1800,cur_size=0x1a0,peak_size=0x9e0
flash_prot,id=3,status=8,pri=1,size=0x400,cur_size=0x100,peak_size=0x174
at_proc,id=4,status=20,pri=10,size=0xc00,cur_size=0x2d0,peak_size=0x5a4
at_uart,id=5,status=8,pri=9,size=0x600,cur_size=0x160,peak_size=0x1e4
tcpip_thread,id=6,status=72,pri=5,size=0x1000,cur_size=0x1e0,peak_size=0x480
hisi_frw,id=7,status=8,pri=4,size=0xc00,cur_size=0x100,peak_size=0x660
TcpServerTask,id=9,status=8,pri=15,size=0x1000,cur_size=0x310,peak_size=0x880
Bootstrap,id=10,status=8192,pri=14,size=0x800,cur_size=0x190,peak_size=0x340
Broadcast,id=11,status=8192,pri=7,size=0x800,cur_size=0x190,peak_size=0x260
hiview,id=12,status=8192,pri=15,size=0x800,cur_size=0x190,peak_size=0x5a0
cpup:
runtime:
0d-00h-00m-16s
OK


[23:30:01.149]发→◇AT+IFCFG
□
[23:30:01.153]收←◆AT+IFCFG
+IFCFG:wlan0,ip=192.168.137.56,netmask=255.255.255.0,gateway=192.168.137.1,ip6=FE80::B6C9:B9FF:FEAF:6903,HWaddr=b4:c9:b9:af:69:03,MTU=1500,LinkStatus=1,RunStatus=1
+IFCFG:lo,ip=127.0.0.1,netmask=255.0.0.0,gateway=127.0.0.1,ip6=::1,HWaddr=00,MTU=16436,LinkStatus=1,RunStatus=1
OK


[23:30:18.441]收←◆accept failed, -1, 12
do_cleanup...
disconnect to AP ...
netifapi_dhcp_stop: 0
+NOTICE:DISCONNECTED
OnWifiConnectionChanged 120, state = 0, info = 
bssid: 70:C9:4E:E3:00:4B, rssi: 0, connState: 0, reason: 3, ssid: 
Disconnect: 0
UnRegisterWifiEvent: 0
RemoveDevice: 0
DisableWifi: 0
disconnect to AP done!

accpet会阻塞,直到PC上启动客户端测试连接命令:

$ nc 192.168.137.56 5678
12345

PC上客户端命令刚启动,板子上就会 accept failed

查了 lwip/errno.h,错误码12是:

#define  ENOMEM          12  /* Out of memory */

但是,我通过SYSINFO查询到,系统还有空闲内存可用

Attachments
19406 swxu 1602213630 total 1 participants

Comments (1)

19406 swxu 1602213630
许思维 2020-11-06 13:08

原因:LwIP和Linux的Socket API实现差异引起的问题,

  1. Linux上传给bind的addrlen参数可以填0(和addr参数填NULL同样的效果);
  2. 这里的LwIP上,填0就会出现这个问题;

应该的行为:错误码设置为 EINVAL 提示参数错误;

解决方法:bind之前添加,clientAddrLen = sizeof(clientAddr);

Sign in to comment

Assignees
Labels
Not set
Projects
Milestones
Branches
Planed to start
Not set
Planed to end
Not set
Top level
Priority
1
https://git.oschina.net/openharmony/vendor_hisi_hi3861_hi3861.git
git@git.oschina.net:openharmony/vendor_hisi_hi3861_hi3861.git
openharmony
vendor_hisi_hi3861_hi3861
vendor_hisi_hi3861_hi3861

Search