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 文件修改地方
/**
*/ 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
|