From afda158e9c5d83ceffc8dff6d7688ef785ed1935 Mon Sep 17 00:00:00 2001 From: hayden zhou Date: Fri, 2 May 2025 12:19:45 +0800 Subject: [PATCH] add support of ipv6 --- socket.c | 98 +++++++++++++++++++++++++++++++++++++++++------------- webbench.c | 16 ++++++--- 2 files changed, 86 insertions(+), 28 deletions(-) diff --git a/socket.c b/socket.c index b7af54a..7f73efc 100644 --- a/socket.c +++ b/socket.c @@ -12,7 +12,8 @@ environment: DEC Ultrix 4.3 description: UNIX sockets code. ***********************************************************************/ - + +#include #include #include #include @@ -25,34 +26,83 @@ #include #include #include +#include -int Socket(const char *host, int clientPort) + +// On success, returns a non-null pointer to dst. NULL is returned if there was an +// error, with errno set to indicate the error +static const char* sock_ntop_host(char* dst, const struct sockaddr* sa) { - int sock; - unsigned long inaddr; - struct sockaddr_in ad; - struct hostent *hp; - - memset(&ad, 0, sizeof(ad)); - ad.sin_family = AF_INET; - - inaddr = inet_addr(host); - if (inaddr != INADDR_NONE) - memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr)); + if (dst == NULL) + return NULL; + + if (sa->sa_family == AF_INET) + { + struct sockaddr_in* sin = (struct sockaddr_in*)sa; + return inet_ntop(AF_INET, &sin->sin_addr, dst, 128); + } +#ifdef AF_INET6 + else if (sa->sa_family == AF_INET6) + { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)sa; + return inet_ntop(AF_INET6, &sin6->sin6_addr, dst, 128); + } +#endif else { - hp = gethostbyname(host); - if (hp == NULL) - return -1; - memcpy(&ad.sin_addr, hp->h_addr, hp->h_length); + fprintf(stderr, "address family not support %d", sa->sa_family); + return NULL; } - ad.sin_port = htons(clientPort); - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) - return sock; - if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0) +} + +int Socket(int ipv6, const char* host, int clientPort) +{ + int sock = -1; + int error; + struct addrinfo hints; + struct addrinfo *result, *rp; + char servip[128]; + + bzero(&hints, sizeof(hints)); + if (ipv6) + hints.ai_family = AF_INET6; + else + hints.ai_family = AF_INET; + + hints.ai_socktype = SOCK_STREAM; + char strport[6]; + sprintf(strport, "%d", clientPort); + error = getaddrinfo(host, strport, &hints, &result); + if (error) + { + fprintf(stderr, "socket: getaddrinfo error %s\n", gai_strerror(error)); return -1; + } + + for (rp = result; rp != NULL; rp = rp->ai_next) + { + // bzero(&servip, sizeof(servip)); + // if (sock_ntop_host(servip, rp->ai_addr) == NULL) + // fprintf(stderr, "socket: host_inet_ntop error %s\n", strerror(errno)); + // else + // printf("server ip %s\n", servip); + + if ((sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1) + { + // fprintf(stderr, "socket: create socket error %s\n", rp->ai_addr); + continue; + } + + if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) + break; + + close(sock); + } + + freeaddrinfo(result); + + if (rp == NULL) + return -1; + return sock; } - diff --git a/webbench.c b/webbench.c index 318a8fc..3c18f9d 100644 --- a/webbench.c +++ b/webbench.c @@ -19,7 +19,7 @@ #include "socket.c" #include #include -#include +// #include #include #include #include #include @@ -41,6 +41,7 @@ int http10=1; /* 0 - http/0.9, 1 - http/1.0, 2 - http/1.1 */ #define PROGRAM_VERSION "1.5" int method=METHOD_GET; int clients=1; +int ipv6=0; // 0 disable, 1 enable int force=0; int force_reload=0; int proxyport=80; @@ -69,6 +70,7 @@ static const struct option long_options[]= {"version",no_argument,NULL,'V'}, {"proxy",required_argument,NULL,'p'}, {"clients",required_argument,NULL,'c'}, + {"ipv6", no_argument, &ipv6, 1}, {NULL,0,NULL,0} }; @@ -98,6 +100,7 @@ static void usage(void) " --head Use HEAD request method.\n" " --options Use OPTIONS request method.\n" " --trace Use TRACE request method.\n" + " --ipv6 Use IPV6." " -?|-h|--help This information.\n" " -V|--version Display program version.\n" ); @@ -204,8 +207,13 @@ int main(int argc, char *argv[]) else printf("%d clients",clients); + if (ipv6 == 1) + printf(" IPV6"); + else + printf(" IPV4"); + printf(", running %d sec", benchtime); - + if(force) printf(", early socket close"); if(proxyhost!=NULL) printf(", via proxy server %s:%d",proxyhost,proxyport); if(force_reload) printf(", forcing reload"); @@ -329,7 +337,7 @@ static int bench(void) FILE *f; /* check avaibility of target server */ - i=Socket(proxyhost==NULL?host:proxyhost,proxyport); + i=Socket(ipv6, proxyhost==NULL?host:proxyhost,proxyport); if(i<0) { fprintf(stderr,"\nConnect to server failed. Aborting benchmark.\n"); return 1; @@ -463,7 +471,7 @@ void benchcore(const char *host,const int port,const char *req) return; } - s=Socket(host,port); + s=Socket(ipv6, host,port); if(s<0) { failed++;continue;} if(rlen!=write(s,req,rlen)) {failed++;close(s);continue;} if(http10==0)