一、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
}