24 April 2017, 21:03 | #1 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Misunderstanding Sockets
Hi all!
I hope that you could help me understand socket and point me what's wrong with my code I have been trying to implement a kind of "ping" function without success Essentially, I want the code to connect and select (?) an IP address and tell me if the address is alive or to timeout and tell me that the address is dead. Here is my code (without some error checks). The problems are:
Code:
_http_ping_server("91.205.187.246", "80"); // Alive and well _http_ping_server("132.207.170.31", "80"); // Down but existing _http_ping_server("133.200.160.13", "80"); // Non-existing // From http://stackoverflow.com/questions/2597608/c-socket-connection-timeout/2597774#2597774 static int _http_ping_server( IN char *addr, IN char *port) { struct sockaddr_in *remote = NULL; int result = 0; int sock = -1; fd_set fd_read; fd_set fd_write; fd_set fd_excpt; struct timeval tv; int so_error = 0; long len = 0; long one = 1; // Create TCP socket if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { goto _RETURN_ERROR; } // Set non-blocking mode // IoctlSocket(sock, FIONBIO, (void *)&one); // Set remote->sin_addr.s_addr remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in)); remote->sin_family = AF_INET; _inet_pton(AF_INET, addr, (void *)(&(remote->sin_addr.s_addr))); remote->sin_port = htons(atoi(port)); // Connect to server if(connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0) { printf("HERE0 %d\n", errno); FD_ZERO(&fd_read); FD_ZERO(&fd_write); FD_ZERO(&fd_excpt); tv.tv_sec = 3; tv.tv_usec = 0; printf("HERE1 %ld\n", select(sock + 1, &fd_read, &fd_write, &fd_excpt, &tv)); len = sizeof(so_error); getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len); printf("HERE2 %d\n", so_error); printf("HERE3 %ld\n", FD_ISSET(sock, &fd_read)); printf("HERE4 %ld\n", FD_ISSET(sock, &fd_write)); printf("HERE5 %ld\n", FD_ISSET(sock, &fd_excpt)); } else { printf("CONNECTED\n"); } ... |
24 April 2017, 21:48 | #2 |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,104
|
Looks like you're missing a call to FD_SET() before select()
|
25 April 2017, 00:59 | #3 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Hi Paraj!
Thanks, I added the calls to FD_SET() but same behaviour... What puzzles me in particular is that using port 80 yields "0" everywhere while using port 2000 makes the call to select() sets so_errno to 10061 but not when the IP address is non-existing??? I must be missing something here? Cheers! |
25 April 2017, 21:07 | #4 | |
dev
|
Quote:
Port 1 to 1024 are for historical reasons classified as privileged ports. Depending on your TCP/IP stack this could explain the difference in behavior, even if it sounds odd. As far as I can tell, select should only return 0 on timeout. Here is a working example with BSD sockets of what you want to do. Look for the bold line. Code:
/* * tcping.c * * Copyright (c) 2002-2008 Marc Kirchner <mail(at)marc(dash)kirchner(dot)de> * * tcping is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * tcping is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with ms++. If not, see <http://www.gnu.org/licenses/>. * * tcping does a nonblocking connect to test if a port is reachable. * Its exit codes are: * -1 an error occured * 0 port is open * 1 port is closed * 2 user timeout */ #define VERSION 1.3.5 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #ifdef HAVE_STRINGS_H #include <strings.h> #endif #include <unistd.h> #include <sys/time.h> #include <fcntl.h> #include <arpa/inet.h> #include <netdb.h> void usage(); int main (int argc, char *argv[]) { int sockfd; struct sockaddr_in addr; struct hostent *host; int error = 0; int ret; socklen_t errlen; struct timeval timeout; fd_set fdrset, fdwset; int verbose=1; int c; char *cptr; long timeout_sec=0, timeout_usec=0; int port=0; if (argc < 3) { usage(argv[0]); } while((c = getopt(argc, argv, "qt:u:")) != -1) { switch(c) { case 'q': verbose = 0; break; case 't': cptr = NULL; timeout_sec = strtol(optarg, &cptr, 10); if (cptr == optarg) usage(argv[0]); break; case 'u': cptr = NULL; timeout_usec = strtol(optarg, &cptr, 10); if (cptr == optarg) usage(argv[0]); break; default: usage(argv[0]); break; } } sockfd = socket (AF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof(addr)); if ((host = gethostbyname(argv[optind])) == NULL) { if (verbose) #ifdef HAVE_HSTRERROR fprintf(stderr, "error: %s\n", hstrerror(h_errno)); #else fprintf(stderr, "error: host not found"); #endif exit(-1); } memcpy(&addr.sin_addr, host->h_addr_list[0], host->h_length); addr.sin_family = host->h_addrtype; /* always AF_INET */ if (argv[optind+1]) { cptr = NULL; port = strtol(argv[optind+1], &cptr, 10); if (cptr == argv[optind+1]) usage(argv[0]); } else { usage(argv[0]); } addr.sin_port = htons(port); fcntl(sockfd, F_SETFL, O_NONBLOCK); if ((ret = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr))) != 0) { if (errno != EINPROGRESS) { #ifdef HAVE_SOLARIS /* solaris immediately returns ECONNREFUSED on local ports */ if (errno == ECONNREFUSED) { if (verbose) fprintf(stdout, "%s port %s closed.\n", argv[optind], argv[optind+1]); close(sockfd); return(1); } else { #endif if (verbose) fprintf(stderr, "error: %s port %s: %s\n", argv[optind], argv[optind+1], strerror(errno)); return (-1); #ifdef HAVE_SOLARIS } #endif } FD_ZERO(&fdrset); FD_SET(sockfd, &fdrset); fdwset = fdrset; timeout.tv_sec=timeout_sec + timeout_usec / 1000000; timeout.tv_usec=timeout_usec % 1000000; if ((ret = select(sockfd+1, &fdrset, &fdwset, NULL, timeout.tv_sec+timeout.tv_usec > 0 ? &timeout : NULL)) == 0) { /* timeout */ close(sockfd); if (verbose) fprintf(stdout, "%s port %s user timeout.\n", argv[optind], argv[optind+1]); return(2); } if (FD_ISSET(sockfd, &fdrset) || FD_ISSET(sockfd, &fdwset)) { errlen = sizeof(error); if ((ret=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &errlen)) != 0) { /* getsockopt error */ if (verbose) fprintf(stderr, "error: %s port %s: getsockopt: %s\n", argv[optind], argv[optind+1], strerror(errno)); close(sockfd); return(-1); } if (error != 0) { if (verbose) fprintf(stdout, "%s port %s closed.\n", argv[optind], argv[optind+1]); close(sockfd); return(1); } } else { if (verbose) fprintf(stderr, "error: select: sockfd not set\n"); exit(-1); } } /* OK, connection established */ close(sockfd); if (verbose) fprintf(stdout, "%s port %s open.\n", argv[optind], argv[optind+1]); return 0; } void usage(char *prog) { fprintf(stderr, "error: Usage: %s [-q] [-t timeout_sec] [-u timeout_usec] <host> <port>\n", prog); exit(-1); } Last edited by cla; 27 April 2017 at 17:54. |
|
25 April 2017, 21:27 | #5 |
Amigan
Join Date: Feb 2012
Location: London
Posts: 1,311
|
To add to this, only root can listen on ports 1 to 1024. What this means for Amiga stacks I have no idea!
|
25 April 2017, 21:47 | #6 | |
dev
|
Quote:
But thats another story |
|
25 April 2017, 22:50 | #7 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Hi Cla and Nogginthenog!
Thank you so much Cla for your help! I am going to try tonight! Thanks Nogginthenog for the precision! Will keep you posted! Cheers! |
28 April 2017, 18:41 | #8 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Hi Cla and all!
So, I have tried your example but without any luck Below is the code that I used. I believe the problem is with the functions fnctl() and IoctlSocket():
I must be missing something!? Thanks! Code:
int sockfd; struct sockaddr_in addr; struct hostent *host; int error = 0; int ret; long errlen; struct timeval timeout; fd_set fdrset; fd_set fdwset; int c; char *cptr; long timeout_sec = 0; long timeout_usec = 0; long one = 1; sockfd = socket (AF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof(addr)); if ((host = gethostbyname(ip)) == NULL) { fprintf(stderr, "error: host not found"); return RETURN_ERROR; } memcpy(&addr.sin_addr, host->h_addr_list[0], host->h_length); addr.sin_family = host->h_addrtype; /* always AF_INET */ addr.sin_port = htons(atoi(port)); // ret = fcntl(sockfd, F_GETFL, 0); // fcntl(sockfd, F_SETFL, ret | O_NONBLOCK); printf("IoctSocket returns %ld\n", IoctlSocket(sockfd, FIONBIO, (void *)&one)); if ((ret = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr))) != 0) { if (errno != EINPROGRESS) { if (errno == ECONNREFUSED) { fprintf(stdout, "%s port %s closed.\n", ip, port); close(sockfd); return(1); } else { fprintf(stderr, "error: %s port %s: %d\n", ip, port, errno); return RETURN_ERROR; } } fprintf(stdout, "%s port %s THERE.\n", ip, port); FD_ZERO(&fdrset); FD_SET(sockfd, &fdrset); fdwset = fdrset; timeout_sec = 0; timeout_usec = 3; timeout.tv_sec=timeout_sec + timeout_usec / 1000000; timeout.tv_usec=timeout_usec % 1000000; if ((ret = select(sockfd+1, &fdrset, &fdwset, NULL, timeout.tv_sec+timeout.tv_usec > 0 ? &timeout : NULL)) == 0) { /* timeout */ close(sockfd); fprintf(stdout, "%s port %s user timeout.\n", ip, port); return RETURN_ERROR; } if (FD_ISSET(sockfd, &fdrset) || FD_ISSET(sockfd, &fdwset)) { errlen = sizeof(error); if ((ret=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &errlen)) != 0) { /* getsockopt error */ fprintf(stderr, "error: %s port %s: getsockopt: %d\n", ip, port, errno); close(sockfd); return RETURN_ERROR; } if (error != 0) { fprintf(stdout, "%s port %s closed.\n", ip, port); close(sockfd); return RETURN_ERROR; } } else { fprintf(stderr, "error: select: sockfd not set\n"); return RETURN_ERROR; } } /* OK, connection established */ close(sockfd); fprintf(stdout, "%s port %s open.\n", ip, port); return RETURN_OK; |
30 April 2017, 16:40 | #9 |
dev
|
Hi Tygre and all!
I don't know if you are using AmiTCP? I tried to do non-blocking TCP socket with version 4.x but I never managed to it to work. Non-blocking UDP sockets are no problem but I doubt AmiTCP supports non-blocking TCP socket. While I was working on some other network programs using the AmiTCP TCP/IP stack, I discovered several socket flags which was not supported. SO_RCVTIMEO was one of them. If you are really serious about socket programming on AmigaOS 3.x I think you should try Roadshow. Otherwise accepting a 10 seconds timeout is probably the best solution. |
30 April 2017, 20:31 | #10 | ||
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Hi!
Quote:
Quote:
Thanks in advance! |
||
01 May 2017, 00:18 | #11 | |
dev
|
Quote:
Code:
socket(AF_INET, SOCK_DGRAM, 0) What you are missing is documentation for the TCP/IP stack that you are using. I also had troubles with the UAE bsd socket library since it turned out to be different from AmiTCP (which I used as a reference). There used to be some bsdsocket.library documentation available at www.kuchinka.cz but it is not available anymore. Maybe related to UAE bsdsocket.library inconsistensy: http://eab.abime.net/showthread.php?t=86532 And here are the official (AmigaOS 4.1) docs: http://wiki.amigaos.net/amiga/autodo...socket.doc.txt |
|
03 September 2017, 20:54 | #12 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Hi Cla and all!
Thanks Cla for pointing out this implementation of ping for AmigaOS I'm going to try it out, hopefully I'll manage to make it work Cheers! |
01 January 2019, 05:17 | #13 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Hi all and Cla!
Happy new year 2019 @Cla, I tried to recompile your implementation of http_ping but I don't have definitions for SIGALRM and alarm(). Could you help me? Cheers! |
01 January 2019, 12:34 | #14 |
Registered User
Join Date: Dec 2018
Location: Cambridge
Posts: 17
|
On Linux, I have always used the below code. Connect functions are Blocking and its annoying
https://github.com/RichardPar/tcpser...1/src/ip.c#L97 |
01 January 2019, 14:42 | #15 | |
Registered User
Join Date: Sep 2014
Location: Poland
Posts: 175
|
Quote:
|
|
01 January 2019, 19:12 | #16 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Hi RichardP and Ami!
Thanks for your suggestions but still stuck... Ami, I gave some suggestion in your thread Cheers! |
07 February 2019, 21:10 | #17 | |
dev
|
Quote:
I don't know if it is still an issue for you. If it is, here is a solution: alarm() is suppose to handle timeout. When the alarm is triggered after a certain amount of time, handle_alarm() is called, which closes the connection. The same can be achieved using an Amiga timer event. I assume it will interrupt the blocking socket call, send(), in line 483. All in all, it is not that hard. Just takes a lot of time to implement, test and so on. Cheers |
|
08 February 2019, 19:57 | #18 | |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,434
|
Hi Cla!
Quote:
Best! |
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Anyone knows where to get 68000 sockets? | amigasith | support.Hardware | 47 | 08 June 2020 20:14 |
Sockets Simms angled for A4000D | Cosmos | MarketPlace | 13 | 15 March 2010 15:35 |
SIMM sockets with metal clips | amigakit.com | MarketPlace | 0 | 07 November 2008 15:48 |
23 pin D-SUB female sockets | manicx | support.Hardware | 8 | 09 October 2004 00:15 |
What, if anything, do the extra ROM sockets on the A1000 do? | Computolio | support.Hardware | 4 | 16 September 2004 02:24 |
|
|