avinash avinash - 1 month ago 10
C++ Question

SO_LINGER option not causing close() to wait

I wrote the following code in order to make an echo server (data I write to stdout moves from my PC to server and back to my PC). In the code I set the SO_LINGER option in the socket. So when I pressed Ctrl+C which caused client.cpp to send a FIN to server.cpp, the client.cpp's close() should wait for 10s for server.cpp's socket to send back a FIN.

But what i found was that client.cpp immediately finished execution and exited after Ctrl+C was pressed and even the close() funcion didn't return -1 which it should have if the other side doesn't send FIN before the time mentioned in l_linger expires (I am sure that the server didn't send a FIN or it must have been listed in tcpdump.) The server side didn't send a FIN unless I pressed Ctrl+C on its terminal. The tcpdump until I pressed Ctrl+C on the server's terminal is shown in the screenshot:



The highlighted lines above are client's FIN.

client.cpp:

int main()
{
int clifd;
clifd=socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(3345);
inet_aton("127.0.0.1", &(serv.sin_addr));

linger lin;
unsigned int y=sizeof(lin);
lin.l_onoff=1;
lin.l_linger=10;
setsockopt(clifd,SOL_SOCKET, SO_LINGER,(void*)(&lin), y);

connect(clifd, (sockaddr*)(&serv), sizeof(serv));
int n,m;
char data[100];
char recvd[100];
for(;;)
{
fgets(data, 100,stdin );
n=strlen(data);
cout<<"You have written "<<n<<endl;

if(n>0)
{
while(n>0)
{
m=write(clifd,data,n);
n=n-m;
}
}

n=read(clifd, recvd, 100);
cout<<"Server echoed back "<<n<<endl;

if(n>0)
{
while(n>0)
{
m=fputs(data,stdout);
cout<<"m is"<<m<<endl;
fflush(stdout);
n=n-m;
}
//cout<<data<<endl;
}
}
int z=close(clifd);
if(z==-1)
cout<<"close returned -1 "<<endl; ***//this doesn't get printed***
}


server.cpp:

void reflect(int x)
{
int n;
int m;
char data[100];
cout<<"Entered reflect function"<<endl;

for(;;)
{
n=read(x,data, 100);
cout<<"Client sent "<<n<<endl;

if(n>0)
{
while(n>0)
{
m=write(x,data,n);
n=n-m;
}
cout<<"Successfully echoed back to client"<<endl;
}
}//end of for loop
}

int main()
{
sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(3345);
inet_aton("127.0.0.1", &(serv.sin_addr));

int servfd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int x;
x=bind(servfd, (sockaddr*)(&serv), sizeof(serv));

cout<<"Bind returned"<<x<<endl; //this displays x as 0

listen(servfd, 5);
sockaddr cli;
int connfd;
pid_t id=-1;
socklen_t siz=sizeof(cli);
for(;;)
{
if((connfd=accept(servfd, &cli, &siz))>=0)
id=fork();

if(id==0)
reflect(connfd);
else
continue;
}
}


Why is client's close() not waiting?

EJP EJP
Answer

So, the client.cpp 's close() should wait for 10s for server.cpp 's socket to send back a FIN.

That's not correct. It should wait for all the outgoing data and the outgoing FIN to be sent, or for the timer to expire. There is no statement anywhere that entitles you to expect it to wait for an incoming FIN.