Skip to main content
Explorer
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?

  • August 26, 2022
  • 0 replies
  • 1016 views
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.