rtthread系统下lwip TIME_WAIT问题

    在rtthread系统测试socket server时发现首次启动可以绑定成功,再次启动时会bind失败,网上提到几种方法:SO_REUSEADDR、 SO_REUSEPORT 、SO_LINGER。尝试之后发现调用函数都失败了。

    查看LWIP源码发现有 LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULTLWIP_SO_LINGERSO_REUSE三处定义比较可疑,然后直接在编译LWIP源码时在makefile文件中加上-DSO_REUSE=1   -DLWIP_SO_LINGER=1后,SO_REUSEPORT 依旧失败,但是SO_REUSEADDR以及SO_LINGER成功了。再次启动socket server时也可以正常绑定了。

    我最终只用了-DSO_REUSE=1,然后测试代码中调用lwip_setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int))达到了预期效果。

/*************************************************************************

> File Name: client.c

> Author:

> Mail:

> Created Time: 2019年09月20日 星期五 17时20分55秒

************************************************************************/

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/socket.h>

#include <log.h>

#include "bcm_wifi.h"

#include "lwip/tcpip.h"

//#include <utils/plat_log.h>

//#define LOG_TAG "dong_client"

static int cmd_dong_client(int argc, char ** argv[])

{

    int i = 0;

    struct sockaddr_in serv_addr;

    int sock = 0;

    char server_ip[20];

    int port = 0;

    char msg_buffer[1024];

    int ret = 0;

    memset(server_ip, 0, sizeof(server_ip));

    memset(&serv_addr, 0, sizeof(serv_addr));

    if(argc < 3){

        printk("Usage: dong_client server_ip port\n");

        printk("\tdong_client 192.168.19.199 8888\n");

        return -1;

    }else{

        memcpy(server_ip, argv[1], strlen(argv[1]));

        port = strtol(argv[2], NULL, 0);

        printk("server_ip:%s, port:%d\n", server_ip, port);

    }

    serv_addr.sin_family = AF_INET;

    serv_addr.sin_addr.s_addr = inet_addr(server_ip);

    serv_addr.sin_port = htons(port);

    sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);//IPPROTO_IP 0, IPPROTO_TCP 6

    if(sock == -1){

        printk("socket failed\n");

        return -1;

    }

    if(lwip_connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0){

        printk("connect failed\n");

        goto _exit;

    }

    {

        struct sockaddr_in serv, guest;

        socklen_t serv_len = sizeof(serv);

        socklen_t guest_len = sizeof(guest);

        lwip_getsockname(sock, &guest, &guest_len);

        lwip_getpeername(sock, &serv, &serv_len);

        printk("guest addr:%s, port:%d\n", inet_ntoa(guest.sin_addr.s_addr), ntohs(guest.sin_port));

        printk("server addr:%s, port:%d\n", inet_ntoa(serv.sin_addr.s_addr), ntohs(serv.sin_port));

    }

    memset(msg_buffer, 0, sizeof(msg_buffer));

    sprintf(msg_buffer, "dong_socket\n");

    ret = lwip_write(sock, msg_buffer, strlen(msg_buffer));

    printk("lwip_write ret = %d, %s\n", ret, msg_buffer);

    if (ret == -1){

        printf("lost connection\n");

        goto _exit;

    }

    while(1){

        i++;

        memset(msg_buffer, 0, sizeof(msg_buffer));

        ret = lwip_read(sock, msg_buffer, sizeof(msg_buffer)-1);

        printk("\n---------------------------\n");

        printk("lwip_read ret = %d, %s\n", ret, msg_buffer);

        if (ret == -1){

            printf("lost connection\n");

            goto _exit;

        }

        ret = lwip_write(sock, msg_buffer, strlen(msg_buffer));

        printk("lwip_write ret = %d, %s\n", ret, msg_buffer);

        if (ret == -1){

            printf("lost connection\n");

            goto _exit;

        }

        if(strcmp(msg_buffer, "quit") == 0){

            printk("Bye!\n");

            break;

        }

        sleep(1);

    }

_exit:

    printk("close socket\n");

    //close(sock);

    lwip_close(sock);

    printk("---------------dong_client exit---------------\n");

    return 0;

}

FINSH_FUNCTION_EXPORT_ALIAS(cmd_dong_client, __cmd_dong_client, socket client test);

int cmd_dong_server(int argc, char ** argv[])

{

    int ret = 0;

    int serv_sock = 0;

    int clnt_sock = 0;

    struct sockaddr_in serv_addr;

    struct sockaddr_in clnt_addr;

    socklen_t clnt_addr_size = sizeof(clnt_addr);

    int port = 0;

    char msg_buffer[1024];

    if(argc < 2){

        printk("Usage: dong_server port\n");

        printk("\tdong_server 8888\n");

        return -1;

    }else{

        port = strtol(argv[1], NULL, 0);

        printk("port:%d\n", port);

    }

    memset(&serv_addr, 0, sizeof(serv_addr));

#if 0

    uint8_t server_ip_bytes[4];

    extern void mhd_sta_dhcpc_get_ip_address(char *);

    mhd_sta_dhcpc_get_ip_address(server_ip_bytes);

    printf("mhd_sta_dhcpc_get_ip_address: %d.%d.%d.%d\n", server_ip_bytes[0], server_ip_bytes[1], server_ip_bytes[2], server_ip_bytes[3]);

    memset(msg_buffer, 0, sizeof(msg_buffer));

    sprintf(msg_buffer, "%d.%d.%d.%d", server_ip_bytes[0], server_ip_bytes[1], server_ip_bytes[2], server_ip_bytes[3]);

    serv_addr.sin_addr.s_addr = inet_addr(msg_buffer);

#else

    serv_addr.sin_addr.s_addr = INADDR_ANY;//htonl(INADDR_ANY);

#endif

    serv_addr.sin_family = AF_INET;

    serv_addr.sin_port = htons(port);

    serv_sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);//IPPROTO_IP 0, IPPROTO_TCP 6

    if(serv_sock == -1){

        printk("socket failed\n");

        return -1;

    }

#if 1

    int on = 1;

    //try to fix bug when server restart, bind would fail, must define SO_REUSE when compile lwip!!!

    if(lwip_setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) != 0){

        printk("setsockopt SO_REUSEADDR failed\n");

        //goto _exit_server;

    }

    on = 1;

    if(lwip_setsockopt(serv_sock, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)) != 0){

        printk("setsockopt SO_REUSEPORT failed\n");

        //goto _exit_server;

    }

//#else

    //must define LWIP_SO_LINGER when compile lwip!!!

    struct linger so_linger;

    so_linger.l_onoff = 1;

    so_linger.l_linger = 0;

    if(lwip_setsockopt(serv_sock, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)) != 0){

        printk("setsockopt SO_LINGER failed\n");

        //goto _exit_server;

    }

#endif

    ret = lwip_bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    if(ret != 0){

        printk("bind failed\n");

        goto _exit_server;

    }

    ret = lwip_listen(serv_sock, 20);

    if(ret != 0){

        printk("listen failed\n");

        goto _exit_server;

    }

    clnt_sock = lwip_accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);

    if(clnt_sock == -1){

        printk("accept failed\n");

        goto _exit_server;

    }else{

        printk("client addr:%s, port:%d\n", inet_ntoa(clnt_addr.sin_addr.s_addr), ntohs(clnt_addr.sin_port));

    }

    {

        struct sockaddr_in serv, guest;

        socklen_t serv_len = sizeof(serv);

        socklen_t guest_len = sizeof(guest);

        lwip_getsockname(clnt_sock, &serv, &serv_len);

        lwip_getpeername(clnt_sock, &guest, &guest_len);

        printk("guest addr:%s, port:%d\n", inet_ntoa(guest.sin_addr.s_addr), ntohs(guest.sin_port));

        printk("server addr:%s, port:%d\n", inet_ntoa(serv.sin_addr.s_addr), ntohs(serv.sin_port));

    }

    memset(msg_buffer, 0, sizeof(msg_buffer));

    sprintf(msg_buffer, "dong_server\n");

    ret = lwip_write(clnt_sock, msg_buffer, strlen(msg_buffer));

    printk("lwip_write ret = %d, %s\n", ret, msg_buffer);

    if (ret == -1){

        printf("lost connection\n");

        goto _exit_client;

    }

    while(1){

        memset(msg_buffer, 0, sizeof(msg_buffer));

        ret = lwip_read(clnt_sock, msg_buffer, sizeof(msg_buffer)-1);

        printk("\n---------------------------\n");

        printk("lwip_read ret = %d, %s\n", ret, msg_buffer);

        if (ret == -1){

            printf("lost connection\n");

            goto _exit_client;

        }

        ret = lwip_write(clnt_sock, msg_buffer, strlen(msg_buffer));

        printk("lwip_write ret = %d, %s\n", ret, msg_buffer);

        if (ret == -1){

            printf("lost connection\n");

            goto _exit_client;

        }

        if(strcmp(msg_buffer, "quit") == 0){

            printk("Bye!\n");

            break;

        }

        sleep(1);

    }

_exit_client:

    printk("shutdown socket client\n");

    lwip_shutdown(clnt_sock, SHUT_RDWR);

    printk("close socket client\n");

    lwip_close(clnt_sock);

_exit_server:

    printk("shutdown socket server\n");

    lwip_shutdown(serv_sock, SHUT_RDWR);

    printk("close socket server\n");

    lwip_close(serv_sock);

    printk("---------------dong_server exit---------------\n");

    return 0;

}

FINSH_FUNCTION_EXPORT_ALIAS(cmd_dong_server, __cmd_dong_server, socket server test);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值