lkml.org 
[lkml]   [2002]   [Apr]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
Subjectsocket write(2) after remote shutdown(2) problem ?
Hi,

Is the following behaviour correct on a tcp connection:
* the server issues a shutdown(sock, RW)
* the client side socket passes in CLOSE-WAIT state
* the client issues a write on the socket which succeds.

I expected the last write to fail, since the other side is not
capable any more to receive data. Can someone confirm to me one
of the following:
1. behaviour is correct and why.
2. shutdown is buggy.
3. write is buggy.

Thanks.

Attached are sample codes for the "server" and the "client". Test
was done on latest 2.4 and 2.5 kernels.

Stelian.
--
Stelian Pop <stelian.pop@fr.alcove.com>
Alcove - http://www.alcove.com
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

char buf[1024];

int main()
{
int fd;
char * ptr;
struct sockaddr_in addr;
int ready = 0;
fd_set rfds, efds;
int nread;

/* establish connection */

fd = socket (PF_INET, SOCK_STREAM, 0);
if ( -1 == fd) {
perror ("socket");
exit (1);
}

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (INADDR_ANY);
addr.sin_port = 0;
if (bind (fd, (struct sockaddr*)&addr, sizeof (struct sockaddr_in)) != 0) {
perror ("bind");
exit (1);
}

ptr = (char*)&addr.sin_addr.s_addr;
/* ptr[0] = 162; ptr[1] = 0; ptr[2] = 120; ptr[3] = 98;*/
ptr[0] = 127; ptr[1] = 0; ptr[2] = 0; ptr[3] = 1;
addr.sin_port = htons(9999);
if (connect (fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
perror ("connect");
exit (1);
}

FD_ZERO (&rfds);
FD_SET (fd, &rfds);
select (fd+1, &rfds, 0, 0, 0);

/* read everything from socket and print it to stdout */

while (!ready) {
struct timeval tv;

FD_ZERO (&rfds);
FD_SET (fd, &rfds);
FD_ZERO (&efds);
FD_SET (fd, &efds);
memset (&tv, 0, sizeof(tv));

switch (select (fd+1, &rfds, 0, &efds, &tv)) {
case -1:
perror("select");
exit (1);
case 0:
ready = 1;
break;
case 1:
if (FD_ISSET (fd, &efds)) {
fprintf (stderr, "select found exception");
}
nread = read (fd, &buf, 1024);
if (nread == 0)
ready = 1;
else
write (1, &buf, nread);
break;
}
}

/* here lsof will show CLOSE_WAIT */
raise (SIGSTOP);

{
int ret;

if ((ret = write (fd, "QUIT\n", 5)) == -1) {
perror ("write");
exit (1);
}
printf("write ok, ret=%d\n", ret);
}

/* here the socket is orphaned, after write succeeded */
raise (SIGSTOP);

return 0;
}
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

char buf[1024];

int main()
{
int fd, conn;
struct sockaddr_in addr;
socklen_t size;

/* get socket to client, listening on 9999 */

fd = socket (PF_INET, SOCK_STREAM, 0);
if ( -1 == fd) {
perror ("socket");
exit (1);
}

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (INADDR_ANY);
addr.sin_port = htons(9999);
if (bind (fd, (struct sockaddr*)&addr, sizeof (struct sockaddr_in)) != 0) {
perror ("bind");
exit (1);
}

if (-1 == listen (fd, 1)) {
perror ("listen");
exit (1);
}

if (-1 == (conn = accept(fd, (struct sockaddr*)&addr, &size))) {
perror ("accept");
exit (1);
}

/* send some info */

if (write (conn, "Hello client !\n", 15) == -1) {
perror ("write");
exit (1);
}

/* finish */

if (-1 == shutdown (conn, SHUT_RDWR)) {
perror ("shutdown");
exit (1);
}

return 0;
}
\
 
 \ /
  Last update: 2005-03-22 13:22    [W:0.058 / U:9.652 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site