Hello,
I am running a tcp socket server on TM4C129EXL LP and also have multiple LabVIEW tcp clients to communicate with it. I have a router with dhcp enabled ( uC is in auto obtain IP address).
I would like to prepare server side code is to detect if any client is disconnected but not in a conventional way. I mean link layer failure of if the client is out of wifi range and so on.
I made some tests to detect client side connection loss, such as ethernet cable removal btw. the uC and the router, but the following code:
bytesSent = send(clientfd,tcpPacket,HCOM_PACKET_SIZE_1024,0);
executes without any error, bytesSent is a valid number. I read about SO_KEEPALIVE that may help :
Here is my server side code:
void tcpHandler(UArg arg0, UArg arg1) { int status; int clientfd; int server; struct sockaddr_in localAddr; struct sockaddr_in clientAddr; int optval; int optlen = sizeof(optval); socklen_t addrlen = sizeof(clientAddr); Task_Handle taskHandle; Task_Params taskParams; Error_Block eb; server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (server == -1) { System_printf("Error: socket not created.\n"); goto shutdown; } memset(&localAddr, 0, sizeof(localAddr)); localAddr.sin_family = AF_INET; localAddr.sin_addr.s_addr = htonl(INADDR_ANY); localAddr.sin_port = htons(arg0); status = bind(server, (struct sockaddr *)&localAddr, sizeof(localAddr)); if (status == -1) { System_printf("Error: bind failed.\n"); goto shutdown; } status = listen(server, NUMTCPWORKERS); if (status == -1) { System_printf("Error: listen failed.\n"); goto shutdown; } // Set KEEPALIVE option to 1 optval = 1; if (setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { System_printf("Error: setsockopt failed\n"); goto shutdown; } if(getsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) { System_printf("Error: setsockopt failed\n"); goto shutdown; } System_printf("Keepalive value: %d\r\n",optval); System_flush(); while ((clientfd = accept(server, (struct sockaddr *)&clientAddr, &addrlen)) != -1) { System_printf("tcpHandler: Creating thread clientfd = %d\n", clientfd); /* Init the Error_Block */ Error_init(&eb); Mailbox_Handle clientmb = lockMailbox(); if(clientmb == NULL) { System_printf("Unable to get mailbox\r\n"); } /* Initialize the defaults and set the parameters. */ Task_Params_init(&taskParams); taskParams.arg0 = (UArg)clientfd; taskParams.arg1 = (UArg) clientmb; //taskParams.arg1 = (UArg)TCP_Mailbox_Transmit; // here we use the static mailbox created in XCONF taskParams.priority = 1; taskParams.stackSize = 2048; taskHandle = Task_create((Task_FuncPtr)TCP_Receive_Task, &taskParams, &eb); if (taskHandle == NULL) { System_printf("Error: Failed to create new Task\n"); System_flush(); close(clientfd); } taskParams.stackSize = 4096; taskHandle = Task_create((Task_FuncPtr)TCP_Transmit_Task, &taskParams, &eb); if (taskHandle == NULL) { System_printf("Error: Failed to create new Task\n"); System_flush(); close(clientfd); } /* addrlen is a value-result param, must reset for next accept call */ addrlen = sizeof(clientAddr); System_flush(); } System_printf("Error: accept failed.\n"); shutdown: if (server > 0) { close(server); } }
When I start the server with wireshark I don't see any keepalive message btw the nodes. In the ndk\inc\stack\inc\resif.h I made the following changes:
#define DEF_TCP_KEEP_IDLE 600//72000 /* 2 hours */ #define DEF_TCP_KEEP_INTVL 750 /* 75 seconds */ #define DEF_TCP_KEEP_MAXIDLE 600//6000 /* 10 minutes */
But doen't have any effect on keepalive.
My question is what is the proper way to use keepalive and how to configure the IDLE,INTVL,etc. values?