Skip to main content
DPatr.2
Associate III
August 26, 2022
Question

LWIP SOCKET How can server tell if Client disconnected without "warning"? Server on MCU (STM32F429ZIT6, custom board), Client application on Windows I spent two days trying to figure a solution to this problem. Here is my solution, what do you think?

in main.c
int connectionClosed = 0;
...
Setup routine of socket
...
 while(1){
	 sin_size = sizeof(struct sockaddr_in);
	 new_socket = lwip_accept(s_create, (struct sockaddr *)&client_addr, &sin_size); 
	 if (new_socket > 0){
 
		 msgSize = sprintf(printMsg, "New client connected from IP: %s, Port: %d\r\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
		 HAL_UART_Transmit(&huart3, (uint8_t*)printMsg, msgSize, 10);
		 connectionClosed = 0;
 
		 while(strncmp(recvBuff,"close", 5)){
 
			 if (connectionClosed) {
				 goto socket_close;
			 }
 
			 memset(recvBuff, 0, sizeof(recvBuff));
			 retVal = lwip_recv(new_socket, recvBuff, sizeof(recvBuff), MSG_DONTWAIT); 
			 // Process buffer
			 processMsg(recvBuff);
 
			 //Toggle LED every ~second
			 updateLED();
 
			 osDelay(1);
		 }// End of client connected loop
 
		 socket_close:
		 lwip_close(new_socket);
 
	 }
}
 
 
in sockets.c
extern connectionClosed;
 
static void
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
{
 int s, check_waiters;
 struct lwip_sock *sock;
 SYS_ARCH_DECL_PROTECT(lev);
 
 LWIP_UNUSED_ARG(len);
 
 /* Get socket */
 if (conn) {
 s = conn->socket;
 if (s < 0) {
 /* Data comes in right away after an accept, even though
 * the server task might not have created a new socket yet.
 * Just count down (or up) if that's the case and we
 * will use the data later. Note that only receive events
 * can happen before the new socket is set up. */
 SYS_ARCH_PROTECT(lev);
 if (conn->socket < 0) {
 if (evt == NETCONN_EVT_RCVPLUS) {
 /* conn->socket is -1 on initialization
 lwip_accept adjusts sock->recvevent if conn->socket < -1 */
 conn->socket--;
 }
 SYS_ARCH_UNPROTECT(lev);
 return;
 }
 s = conn->socket;
 SYS_ARCH_UNPROTECT(lev);
 }
 
 sock = get_socket(s);
 if (!sock) {
 return;
 }
 } else {
 return;
 }
 
 check_waiters = 1;
 SYS_ARCH_PROTECT(lev);
 /* Set event as required */
 switch (evt) {
 case NETCONN_EVT_RCVPLUS:
 sock->rcvevent++;
 if (sock->rcvevent > 1) {
 check_waiters = 0;
 }
 break;
 case NETCONN_EVT_RCVMINUS:
 sock->rcvevent--;
 check_waiters = 0;
 break;
 case NETCONN_EVT_SENDPLUS:
 if (sock->sendevent) {
 check_waiters = 0;
 }
 sock->sendevent = 1;
 break;
 case NETCONN_EVT_SENDMINUS:
 sock->sendevent = 0;
 check_waiters = 0;
 break;
 case NETCONN_EVT_ERROR:
 sock->errevent = 1;
 connectionClosed = 1;
 break;
 default:
 LWIP_ASSERT("unknown event", 0);
 break;
 }
 
 if (sock->select_waiting && check_waiters) {
 /* Save which events are active */
 int has_recvevent, has_sendevent, has_errevent;
 has_recvevent = sock->rcvevent > 0;
 has_sendevent = sock->sendevent != 0;
 has_errevent = sock->errevent != 0;
 SYS_ARCH_UNPROTECT(lev);
 /* Check any select calls waiting on this socket */
 select_check_waiters(s, has_recvevent, has_sendevent, has_errevent);
 } else {
 SYS_ARCH_UNPROTECT(lev);
 }
 done_socket(sock);
}
 

This topic has been closed for replies.