IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32 修改LWIP协议 非阻塞方式接受数据 -> 正文阅读

[嵌入式]STM32 修改LWIP协议 非阻塞方式接受数据

STM32移植LWIP协议,套字rev为阻塞模式,SocketServer 处理多个用户连接以及数据手发,可以创建多个任务来单独处理每个client的数据接受。这样消耗的资源相对比较多,都同时调用相同的套字函数rev需要做临界区处理才能正确运行。
如果非阻塞方式可以在一个任务里面处理所有的client数据不停的轮询就可以了。
LWIP协议修改地方 sockets.c文件
extern char NOStop;
int
lwip_recvfrom(int s, void *mem, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
struct lwip_sock *sock;
void *buf = NULL;
struct pbuf *p;
u16_t buflen, copylen;
int off = 0;
u8_t done = 0;
err_t err;

LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
sock = get_socket(s);
if (!sock) 
{
	return -1;
}
do 
{
	LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
	/* Check if there is data left from the last recv operation. */
	if (sock->lastdata) 
	{
		buf = sock->lastdata;
	} 
	else 
	{
	
		/* If this is non-blocking call, then check first */
		if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&(sock->rcvevent <= 0)) 
		{
        		if (off > 0) 
			{
          			/* already received data, return that */
				sock_set_errno(sock, 0);
				return off;
			}
			LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
			set_errno(EWOULDBLOCK);
			return -1;
		}
		/* No data was left from the previous operation, so we try to get
		some from the network. */
	if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) 
	{
		
		err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
		if(NOStop)
		{
			return 0;
		}
		
	} 
	else 
	{
		
		err = netconn_recv(sock->conn, (struct netbuf **)&buf);
	}
  		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",err, buf));

  		if (err != ERR_OK) 
	{
		if (off > 0) 
		{
			if (err == ERR_CLSD) 
			{
				/* closed but already received data, ensure select gets the FIN, too */
				event_callback(sock->conn, NETCONN_EVT_RCVPLUS, 0);
			}
			/* already received data, return that */
			sock_set_errno(sock, 0);
			return off;
    		}
   		 /* We should really do some error checking here. */
		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",s, lwip_strerr(err)));
		sock_set_errno(sock, err_to_errno(err));
		if (err == ERR_CLSD) 
		{
			return-2;
		}
		else
		{
			return -1;
		}
	}
	LWIP_ASSERT("buf != NULL", buf != NULL);
	sock->lastdata = buf;
}

if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
  p = (struct pbuf *)buf;
} else {
  p = ((struct netbuf *)buf)->p;
}
buflen = p->tot_len;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
  buflen, len, off, sock->lastoffset));

buflen -= sock->lastoffset;

if (len > buflen)
{
	copylen = buflen;
} 
else
{
	copylen = (u16_t)len;
}

/* copy the contents of the received buffer into
the supplied memory pointer mem */
pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);

	off += copylen;

	if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) 
	{
		LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
		len -= copylen;
	//	if ((len <= 0) ||(p->flags & PBUF_FLAG_PUSH) ||(sock->rcvevent <= 0) ||((flags & MSG_PEEK) != 0)) 
		{
			done = 1;
		}
	} 
	else 
	{
		done = 1;
	}
//	printf("BB:%d\r\n",done);

	/* Check to see from where the data was.*/
	if (done)
	{
		#if !SOCKETS_DEBUG
		if (from && fromlen)
		#endif /* !SOCKETS_DEBUG */
		{
		u16_t port;
		ip_addr_t tmpaddr;
		ip_addr_t *fromaddr;
		union sockaddr_aligned saddr;
		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
		if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP)
		{
			fromaddr = &tmpaddr;
			netconn_getaddr(sock->conn, fromaddr, &port, 0);
		} 
		else 
		{
			port = netbuf_fromport((struct netbuf *)buf);
			fromaddr = netbuf_fromaddr((struct netbuf *)buf);
		}

		#if LWIP_IPV4 && LWIP_IPV6
   		/* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */
   		 if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn)) && IP_IS_V4(fromaddr)) 
		 {
			ip4_2_ipv4_mapped_ipv6(ip_2_ip6(fromaddr), ip_2_ip4(fromaddr));
			IP_SET_TYPE(fromaddr, IPADDR_TYPE_V6);
		}
		#endif /* LWIP_IPV4 && LWIP_IPV6 */

    		IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
    		ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
    		LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
		#if SOCKETS_DEBUG
    		if (from && fromlen)
		#endif /* SOCKETS_DEBUG */
		{
     			if (*fromlen > saddr.sa.sa_len) 
			{
        				*fromlen = saddr.sa.sa_len;
     			 }
      			MEMCPY(from, &saddr, *fromlen);
    		}
  		}
}

	/* If we don't peek the incoming message... */
if ((flags & MSG_PEEK) == 0) 
{
  		/* If this is a TCP socket, check if there is data left in the
     	buffer. If so, it should be saved in the sock structure for next
    	 time around. */
 		 if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) && (buflen - copylen > 0)) 
	{
    		sock->lastdata = buf;
		sock->lastoffset += copylen;
		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
	} 
	else 
	{
		sock->lastdata = NULL;
		sock->lastoffset = 0;
		LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
		if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) 
		{
      			pbuf_free((struct pbuf *)buf);
    		} 
		else 
		{
      			netbuf_delete((struct netbuf *)buf);
    		}
    		buf = NULL;
	}
}

} while (!done);

sock_set_errno(sock, 0);
return off;
}

API_Lib.c 文件修改地方

/**

  • @ingroup netconn_common
  • Receive data: actual implementation that doesn’t care whether pbuf or netbuf
  • is received
  • @param conn the netconn from which to receive data
  • @param new_buf pointer where a new pbuf/netbuf is stored when received data
  • @return ERR_OK if data has been received, an error code otherwise (timeout,
  •            memory error or another error)
    

*/
extern char NOStop;
static err_t
netconn_recv_data(struct netconn *conn, void **new_buf)
{
void *buf = NULL;
u16_t len;

#if LWIP_TCP
API_MSG_VAR_DECLARE(msg);
#if LWIP_MPU_COMPATIBLE
msg = NULL;
#endif
#endif /* LWIP_TCP */

LWIP_ERROR(“netconn_recv: invalid pointer”, (new_buf != NULL), return ERR_ARG;);
new_buf = NULL;
LWIP_ERROR(“netconn_recv: invalid conn”, (conn != NULL), return ERR_ARG;);
#if LWIP_TCP
#if (LWIP_UDP || LWIP_RAW)
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
#endif /
(LWIP_UDP || LWIP_RAW) /
{
if (!sys_mbox_valid(&conn->recvmbox)) {
/
This happens when calling this function after receiving FIN /
return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD;
}
}
#endif /
LWIP_TCP */
LWIP_ERROR(“netconn_recv: invalid recvmbox”, sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);

if (ERR_IS_FATAL(conn->last_err)) {
/* don’t recv on fatal errors: this might block the application task
waiting on recvmbox forever! /
/
@todo: this does not allow us to fetch data that has been put into recvmbox
before the fatal error occurred - is that a problem? /
return conn->last_err;
}
#if LWIP_TCP
#if (LWIP_UDP || LWIP_RAW)
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
#endif /
(LWIP_UDP || LWIP_RAW) /
{
API_MSG_VAR_ALLOC(msg);
}
#endif /
LWIP_TCP */

#if LWIP_SO_RCVTIMEO
if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
#if LWIP_TCP
#if (LWIP_UDP || LWIP_RAW)
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
#endif /* (LWIP_UDP || LWIP_RAW) /
{
API_MSG_VAR_FREE(msg);
}
#endif /
LWIP_TCP */
return ERR_TIMEOUT;
}
#else

if(SYS_ARCH_TIMEOUT==sys_arch_mbox_fetch(&conn->recvmbox, &buf, 10))
//if(sys_arch_mbox_tryfetch (&conn->recvmbox, &buf)==SYS_MBOX_EMPTY);
{

NOStop=1;
return ERR_OK;

}

#endif /* LWIP_SO_RCVTIMEO*/

#if LWIP_TCP
#if (LWIP_UDP || LWIP_RAW)
if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
#endif /* (LWIP_UDP || LWIP_RAW) /
{
/
Let the stack know that we have taken the data. /
/
@todo: Speedup: Don’t block and wait for the answer here
(to prevent multiple thread-switches). */
API_MSG_VAR_REF(msg).conn = conn;
if (buf != NULL) {
API_MSG_VAR_REF(msg).msg.r.len = ((struct pbuf *)buf)->tot_len;
} else {
API_MSG_VAR_REF(msg).msg.r.len = 1;
}

/* don't care for the return value of lwip_netconn_do_recv */
netconn_apimsg(lwip_netconn_do_recv, &API_MSG_VAR_REF(msg));
API_MSG_VAR_FREE(msg);

/* If we are closed, we indicate that we no longer wish to use the socket */
if (buf == NULL) {
  API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
  if (conn->pcb.ip == NULL) {
    /* race condition: RST during recv */
    return conn->last_err == ERR_OK ? ERR_RST : conn->last_err;
  }
  /* RX side is closed, so deallocate the recvmbox */
  netconn_close_shutdown(conn, NETCONN_SHUT_RD);
  /* Don' store ERR_CLSD as conn->err since we are only half-closed */
  return ERR_CLSD;
}
len = ((struct pbuf *)buf)->tot_len;

}
#endif /* LWIP_TCP /
#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
else
#endif /
LWIP_TCP && (LWIP_UDP || LWIP_RAW) /
#if (LWIP_UDP || LWIP_RAW)
{
LWIP_ASSERT(“buf != NULL”, buf != NULL);
len = netbuf_len((struct netbuf
)buf);
}
#endif /* (LWIP_UDP || LWIP_RAW) */

#if LWIP_SO_RCVBUF
SYS_ARCH_DEC(conn->recv_avail, len);
#endif /* LWIP_SO_RCVBUF /
/
Register event with callback */
API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);

LWIP_DEBUGF(API_LIB_DEBUG, (“netconn_recv_data: received %p, len=%“U16_F”\n”, buf, len));

new_buf = buf;
/
don’t set conn->last_err: it’s only ERR_OK, anyway */
return ERR_OK;
}
程序下载地址:https://download.csdn.net/download/sangzijin/25897526

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-30 12:05:27  更:2021-09-30 12:06:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:47:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码