LWIP + TCP接口封装

一、TCP已经提供了SOCKET可以开大 LWIP_SOCKET 这个宏 就可以直接使用相关接口了,否则就要参考SOCKET接口自己实现一个简单的接口 下面是我自己写的例子 代码如下

#if LWIP_SOCKET
#include "lwip/sockets.h" //直接使用LWIP提供的 socket接口

#else

//定义四个链路结构体

#define CONN_NUM      (4)
struct conn_sock {
  /** sockets currently are built on netconns, each socket has one netconn */
  struct netconn *ptcp_conn;//tcp链路指针
 struct pbuf *ptcpbuf;//数据指针
  int connid;
};

static struct conn_sock connects[CONN_NUM];
sys_sem_t                       socksem;//定义互斥量

static int conn_init(void)
{
    static int conn_init_done = 0;
    int i;

    if (conn_init_done) {
        return 0;
    }

    for (i = 0; i < CONN_NUM; i++) {
        connects[i].connid = -1;
        connects[i].ptcp_conn=NULL;
        connects[i].ptcpbuf=NULL;
    }

    if (sys_sem_new(&socksem, 1) != ERR_OK) {
        return -1;
    }


    conn_init_done = 1;
    return 0 ;
}


static struct conn_sock *get_conn(int c)
{
    struct conn_sock *conn = NULL;

    if ((c < 0) || (c >= CONN_NUM)) {
        return NULL;
    }

    conn = &connects[c];

    if (-1 == conn->connid) {
        return NULL;
    }

    return conn;
}

static int newconn(void)
{
    int i;

   sys_arch_sem_wait(&socksem,0);
    for (i = 0; i < CONN_NUM; i++) {
        if (-1==connects[i].connid) {
            connects[i].connid          = i;
         connects[i].ptcp_conn          = NULL;
         connects[i].ptcpbuf          = NULL;
         sys_sem_signal(&socksem);
            return i;
        }
    }
   
    sys_sem_signal(&socksem);
    return -1;
}


static int freeconn(struct conn_sock *conn)
{
    if (NULL == conn)
        return -1;
    sys_arch_sem_wait(&socksem,0);

    if(conn->ptcp_conn)
    {
        netconn_close(conn->ptcp_conn);//关闭链接
        netconn_delete(conn->ptcp_conn);//释放内存
        conn->ptcp_conn =NULL;
    }

    if(conn->ptcpbuf)
    {
        pbuf_free(conn->ptcpbuf);//释放内存
        conn->ptcpbuf =NULL;
    }
    
    conn->connid     = -1;
    sys_sem_signal(&socksem);
       return 0;
}

#endif
 

//打开TCP链路接口 host 域名或者IP地址 port端口号

int HAL_open_tcp_socket(const char *host, uint16_t port)
{
    err_t err;
    uint32_t timeout = 0;
    ip_addr_t remote_addr;
#if LWIP_SOCKET
    int sock = -1;
    struct sockaddr_in server_addr;
    
#if LWIP_DNS
    while(1)
    {
        err = dns_gethostbyname(host, &remote_addr, NULL, 0);//域名获取IP地址
        if ( ERR_OK == err  ) //得不到地址
        {    
            break;
        }
        timeout++;
        if(timeout >3)
        {
            break;
        }
        sys_msleep(1000); //延时1000
    }
#else
    err = ipaddr_aton(host, &remote_addr) ? ERR_OK : ERR_ARG;
#endif

    if ( ERR_OK != err  ) //得不到地址
    {
        return -1;
    }


    sock = socket(AF_INET, SOCK_STREAM, 0);    //创建一个socket套接字sock
    if (sock < 0)
    {
        return -1;
    }
    
    server_addr.sin_family = AF_INET;//服务器设置的地址协议族IPV4
    server_addr.sin_port = htons(port);//服务器设置的端口号
    server_addr.sin_addr.s_addr = remote_addr.addr;//inet_addr(IP_ADDR);//服务器的地址
    memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));

    timeout =0;
    while (connect(sock,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)//连接服务器
    { 
        sys_msleep(200);
        timeout++;
        if(timeout >3)//尝试三次
        {
            closesocket(sock);//若连接失败则关闭socket
            return -1;
        }
    }

    return sock;
    
#else
    struct conn_sock *conn = NULL;
    struct netconn *tcp_conn = NULL;
    int connid = -1;    
    
    //获取IP
#if LWIP_DNS
    while(1)
    {
        err = dns_gethostbyname(host, &remote_addr, NULL, 0);
        if ( ERR_OK == err  ) //得不到地址
        {    
            break;
        }
        timeout++;
        if(timeout >3)
        {
            break;
        }
        sys_msleep(1000); //延时1000
    }
#else
    err = ipaddr_aton(host, &remote_addr) ? ERR_OK : ERR_ARG;
#endif

    if ( ERR_OK != err  )
    {
        return -1;
    }
    
    if(-1==conn_init())
    {
        return -1;
    }

    
    
    if ((connid = newconn()) == -1) 
    {
        return -1;
    }

    if ((conn = get_conn(connid)) == NULL) 
    {
        freeconn(conn);//释放结构体占用
        return -1;
    }

    tcp_conn = netconn_new(NETCONN_TCP);  //创建一个TCP链接
    if(tcp_conn)
    {
        timeout=0;
        while( ERR_OK != netconn_connect(tcp_conn,&remote_addr,port))
        {
            sys_msleep(200);
            timeout++;
            if(timeout >3)//尝试三次
            {
                netconn_close(tcp_conn);
                netconn_delete(tcp_conn);
                tcp_conn =NULL;
                break;
            }
        }
    }
    
    if(NULL==tcp_conn)
    {
        freeconn(conn);//释放结构体占用
        return -1;
    }
    
    conn->ptcp_conn = tcp_conn;
    return connid +1;//上层从1开始
#endif

}

//关闭TCP链路接口

int HAL_close_socket(int fd)
{
#if LWIP_SOCKET

    return closesocket(fd);

#else
    struct conn_sock *conn = NULL;
    int local_fd =fd -1;

    conn = get_conn(local_fd);
    if (NULL == conn) {
        return -1;
    }

    if (freeconn(conn) != 0) {
        return -1;
    }
    return 0;
#endif

}

//TCP读取接口

int HAL_socket_read(int fd, unsigned char *buf, uint32_t len, uint32_t timeout_ms)
{
#if LWIP_SOCKET
    fd_set client_fd_set;
    struct timeval tv;
    int nready;
    
    tv.tv_sec = timeout_ms/1000;
    tv.tv_usec = (timeout_ms % 1000)*1000;
    FD_ZERO(&client_fd_set);
    FD_SET(fd, &client_fd_set);
    nready = select(fd + 1, &client_fd_set, NULL, NULL, &tv);
    if(nready < 0 )
    {
        return -1;
    }
    else
    {
        if(nready >0 )
        {
            if (FD_ISSET(fd, &client_fd_set))  //可以读取
            {
                return recv(fd, buf, len, 0);
            }
        }
        //超时返回0 
        return 0;
    }
    
#else
    struct conn_sock *conn = NULL;
    struct pbuf *pbuf=NULL;
    
    int local_fd =fd -1;
    err_t recv_err;
    u16_t copylen;
    
     
    conn = get_conn(local_fd);
    if (NULL == conn) 
    {
        return -2;
    }

    if(conn->ptcpbuf)
    {
        pbuf =conn->ptcpbuf; //没接收完善的数据
    }
    else
    {
        conn->ptcp_conn->recv_timeout = timeout_ms;//设置超时时间
        recv_err = netconn_recv_tcp_pbuf(conn->ptcp_conn,&pbuf); //接收数据并设置超时
        if( recv_err != ERR_OK)  
        {
            if(recv_err == ERR_CLSD)  //关闭连接
            {
                return -1;
            }
            return 0;
        } 
    }


    if (len > pbuf->tot_len)  //接收到是数据大小
    {
        copylen = pbuf->tot_len;
    } 
    else 
    {
        copylen = (u16_t)len;
    }
    
       pbuf_copy_partial(pbuf, buf, copylen, 0);//拷贝数据到用户层

    if (pbuf->tot_len - copylen > 0) 
    {
        u16_t tot_len = pbuf->tot_len;
        conn->ptcpbuf = pbuf_free_header(pbuf, copylen);  //剩余数据
        //pbuf_free_header 已经实现conn->ptcpbuf->tot_len = pbuf->tot_len - copylen
        if(conn->ptcpbuf->tot_len != (tot_len -copylen))
        {
            //有问题
            conn->ptcpbuf->tot_len = (tot_len -copylen);
        }
    } 
    else 
    {
        conn->ptcpbuf = NULL;
        pbuf_free(pbuf);
    }
    
    return copylen;
#endif

}

//TCP发送数据

int HAL_socket_write(int fd, unsigned char *buf, uint32_t len, uint32_t timeout_ms)
{
#if LWIP_SOCKET

    return send(fd, buf, len, 0);
    
#else
    struct conn_sock *conn = NULL;
    err_t err;
    int local_fd =fd -1;
    conn = get_conn(local_fd);
    if (NULL == conn) 
    {
        return -2;
    }

    err = netconn_write(conn->ptcp_conn ,buf,len,NETCONN_COPY);
    if(err != ERR_OK)
    {
        return -1;
    }
    
    return len;
#endif

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值