Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com From: "Peter Stephens" To: "'Peter A. Castro'" Cc: Subject: RE: recv and errno during a connection reset/closed by peer Date: Mon, 28 Mar 2005 23:42:30 -0500 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Peter, FYI - I tried setting the SO_LINGER and the SO_RCVTIMEO on Linux and on Cygwin (see code below). It makes sense to me that if the timeout has been exceeded then the recv(..., MSG_PEEK) should do something. On Cygwin it doesn't do anything. On Linux it DOES time out, but it returns -1 and errno=EAGAIN. This is an interesting choice for errno (perhaps ECONNABORTED, ESHUTDOWN, ECOMM, ETIME, ETIMEDOUT, EHOSTUNREACH, or ENOLINK would have been better choices), but at least it is consistent. In the case below, every 10.1 seconds I get -1 and errno=EAGAIN from my MSG_PEEK, so it is useable. I may get even better results now by combining the SO_RCVTIMEO with SO_KEEPALIVE now as Juris had suggested. The spec is kinda vague about the response to a MSG_PEEK when the connection is lost, but I think that you could write a book on this subject with all the possible combinations. Pete #include #include #include #include #include #include #include #include #define MAX_CHARS 18 #define MAX_BUF (MAX_CHARS+2) // +2 is for the CRLF void show_status(int fd); void err(char * pre); int handle_it(char * buf); int main(int argc, char **argv) { int lfd=-1, afd=-1; char buf[MAX_BUF]; int vlen=0, temp=0; socklen_t vslen=0; struct linger vlinger; struct timeval vtime; lfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (-1 == lfd) printf("Error at socket(): %i\n", errno); sockaddr_in svc; svc.sin_family = AF_INET; svc.sin_addr.s_addr = inet_addr("192.168.1.244"); svc.sin_port = htons(27015); if (-1 == bind(lfd, (struct sockaddr *) &svc, sizeof(svc))) printf("bind() failed.\n"); if (-1 == listen(lfd, 1 )) printf("Error listening on socket.\n"); printf("Waiting for client to connect...\n"); while( -1 == afd ){ afd = accept( lfd, NULL, NULL ); } printf("Client connected.\n"); // set receive timeout vslen = sizeof(struct timeval); temp = getsockopt(afd, SOL_SOCKET, SO_RCVTIMEO, &vtime, &vslen); if(-1 == temp){ err("Error at getsockopt(SO_RCVTIMEO)"); } else{ vtime.tv_sec=10; vtime.tv_usec=5; vlen = sizeof(struct timeval); temp = setsockopt(afd, SOL_SOCKET, SO_RCVTIMEO, &vtime, vlen); if(-1 == temp){ err("Error at setsockopt(SO_RCVTIMEO)"); } } int ret_val = 0; int done = 0; do{ ret_val = recv(afd, buf, MAX_BUF, MSG_PEEK); if(0 > ret_val) err(" >>> ERRNO"); else if(ret_val > 0){ ret_val = recv(afd, buf, MAX_BUF, 0); buf[ret_val]='\0'; printf("(%i) \t> %s", ret_val, buf); } usleep(250); done = handle_it(buf); }while(!done); printf("Completed\n"); return 0; } -----Original Message----- From: Peter A. Castro [mailto:doctor AT fruitbat DOT org] Sent: Monday, March 28, 2005 7:02 PM To: Peter Stephens Cc: cygwin AT cygwin DOT com Subject: RE: recv and errno during a connection reset/closed by peer On Mon, 28 Mar 2005, Peter Stephens wrote: > Brian > > Are you saying that there is no way to distinguish a dropped > connection from a MSG_PEEK with no data to retrieve? As someone who's seen this behaviour on several platforms, it can happen. I've had to deal with this little annoyance in other products by having a retry counter loop. So many consecutive recv()s of 0 length constitues a closed connection. Something like this might work here as well? > Pete > > P.S. I use this standard: http://www.unix.org/unix03.html . Is this > incorrect? Brians' link is to the Single Unix Spec V2, so it's not all that old. > Peter A. Stephens > ptfoof AT sbcglobal DOT net > > -----Original Message----- > From: Brian Ford [mailto:ford AT vss DOT fsi DOT com] > Sent: Monday, March 28, 2005 11:37 AM > To: Peter Stephens > Cc: cygwin AT cygwin DOT com > Subject: RE: recv and errno during a connection reset/closed by peer > > On Fri, 25 Mar 2005, Peter Stephens wrote: > >> I boiled this down to nothing(see below). I must be missing >> something basic. > > Yup. > >> I tried the suggestions made so far and it never gets to: >> >> printf(" >>> ERRNO %i\n", errno); >> >> I would expect that on a disconnect (I use putty in telnet or raw >> mode) it would return -1 whether it is doing MSG_PEEK or an actual >> retrieval. No luck. > > Nope (http://www.opengroup.org/onlinepubs/7990989775/xns/recv.html): > > "If no messages are available to be received and the peer has > performed an orderly shutdown, recv() returns 0." > > I think that's what you're missing. > > -- > Brian Ford > Senior Realtime Software Engineer > VITAL - Visual Simulation Systems > FlightSafety International > the best safety device in any aircraft is a well-trained pilot... > > > -- > Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple > Problem reports: http://cygwin.com/problems.html > Documentation: http://cygwin.com/docs.html > FAQ: http://cygwin.com/faq/ > -- Peter A. Castro or "Cats are just autistic Dogs" -- Dr. Tony Attwood -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/