I'm trying to test how to handle a client when a client sends data after a tcp server crash. I wrote a simple client and server code to provide some visual example. The client connects to the tcp server, sends data to the server, and the server reads the data. Now I add a sleep(20) to both implementations so I have time to kill the server process (ctrl-c). The client calls send() again and returns the length of the message. The server is not connected so probably the client will not receive a ACK packet. I assume that the client gets a RST packet but the send() has already returned. The client calls send() a 3rd time but this time, the process ends abruptly without showing any error. The last lines: cout << rsize << endl and everything below it are never called or at least that's what looks like.
When I run this, the client prints rsize values for the first two messages, but not the last one. The server prints only the first message received.
My questions are (1) why is this happening?, and (2)how can I handle correctly a server crash if the client ends abruptly?
I already read other questions related to the topic, but they don't show actual code of how to handle this.
Client code
#include <iostream>
#include <cerrno>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
int serverPort = 65003;
char serverHost[] = "127.0.0.1";
int mySocket;
int bufferSize = 524388;
char responseBuffer[bufferSize];
struct sockaddr clientAddr;
struct sockaddr_in serverAddr;
struct in_addr ipv4addr;
serverAddr.sin_family = AF_INET;
mySocket = socket(AF_INET, SOCK_STREAM, 0);
serverAddr.sin_port = htons (serverPort);
inet_aton(serverHost, &serverAddr.sin_addr);
connect(mySocket, (struct sockaddr*) &serverAddr, sizeof(serverAddr));
int addrLen = sizeof(serverAddr);
getsockname(mySocket, &clientAddr, (socketlen_t*)&addrLen);
ssize_t rsize;
char requestMsg [] = "<This is my test Msg>";
cout << rsize << endl;
rsize = send(mySocket, requestMsg, strlen(requestMsg), 0);
if (rsize != (ssize_t)strlen(requestMsg))
{
cout << strlen(requestMsg) << endl;
cout << strerror(errno) << endl;
}
sleep(20);
char requestMsg2 [] = "<This is my 2nd test Msg>";
rsize = send(mySocket, requestMsg2, strlen(requestMsg2), 0);
cout << rsize << endl;
if (rsize != (ssize_t)strlen(requestMsg2))
{
cout << strlen(requestMsg2) << endl;
cout << strerror(errno) << endl;
}
char requestMsg3 [] = "<This is my 3rd test Msg>";
rsize = send(mySocket, requestMsg3, strlen(requestMsg3), 0);
cout << rsize << endl;
if (rsize != (ssize_t)strlen(requestMsg3))
{
cout << strlen(requestMsg3) << endl;
cout << strerror(errno) << endl;
}
return 0;
}
server code
#include <iostream>
#include <cerrno>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
using namespace std;
int main()
{
int mySocket, connSocket, serverPort;
socketlen_t clientLen;
struct sockaddr_in serverAddr, clientAddr;
int bufferSize = 256;
char buffer[bufferSize];
ssize_t rsize;
mySocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&serverAddr, 0, sizeof(serverAddr));
serverPort = 65003;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(serverPort);
bind(mySocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
listen(mySocket,1);
clientLen = sizeof(clientAddr);
connSocket = accept(mySocket, (struct sockaddr *) &clientAddr, &clientLen);
memset(&buffer, 0, sizeof(buffer));
rsize = read(connSocket, buffer, 255);
cout << buffer << endl;
sleep(20);
}