Messages in this thread | | | Date | Fri, 5 Apr 2002 11:50:39 +0200 | From | Stelian Pop <> | Subject | socket 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; }
| |