getaddrinfo的應用
/***********************************************************************************
函式原型: int getaddrinfo(const char* host,const char* service,const struct addrinfo* hints,struct addrinfo** results);
函式說明:通過hints提示資訊得到滿足提示資訊的結果集,若成功.返回0,若出錯,返回錯誤值,可通過gai_strerror(int err)得到錯誤資訊
**********************************************************************************/
/***********************************************************************************
struct addrinfo {
char* ai_canonname; //主機規範名
int ai_flags;//標誌(AI_PASSIVE多用於伺服器
int ai_family;//網際協議族
int ai_socktype;//套接字型別
int ai_protocol;//套接字採用協議
struct sockaddr* ai_addr;//獲得的主機地址
struct addrinfo* ai_next;//滿足hints下一個addrinfo
}
***********************************************************************************/
小試牛刀:
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
char* what_family(int family) {
switch (family) {
case AF_INET:
return "AF_INET";
case AF_INET6:
return "AF_INET6";
default:
return "unknown family";
}
}
char* what_protocol(int socktype,int protocol) {
switch (protocol) {
case IPPROTO_TCP:
return "TCP";
case IPPROTO_UDP:
return "UDP";
case IPPROTO_SCTP:
return "SCTP";
case 0:
if (socktype == SOCK_DGRAM) {
return "UDP";
}else if (socktype == SOCK_STREAM) {
return "TCP";
}else if (socktype == SOCK_RAW) {
return "SOCK_RAW TCP/UDP";
}else if (socktype == SOCK_RDM) {
return "SOCK_RDM TCP/UDP";
}else if (socktype == SOCK_PACKET) {
return "SOCK_PACKET TCP/UDP";
}else {
return "unknow protocol";
}
default:
return "unknown protocol";
}
}
int main(int argc,char **argv) {
if (argc != 3) {
printf("please add <hostname/ip address> <services-name/port>\n");
exit(1);
}
struct addrinfo hints;
bzero(&hints,sizeof(struct addrinfo));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = 0;
hints.ai_protocol = 0;
struct addrinfo* res;
int err;
if ((err = getaddrinfo(argv[1],argv[2],&hints,&res)) != 0) {
printf("getaddrinfo error: %s\n",gai_strerror(err));
exit(1);
}
struct addrinfo* dummy;
for (dummy = res; dummy != NULL; dummy = dummy->ai_next) {
printf("------------------------------------\n");
printf("host name: %s\n",dummy->ai_canonname);
printf("using family: %s\n",what_family(dummy->ai_family));
printf("using protocol: %s\n",what_protocol(dummy->ai_socktype,dummy->ai_protocol));
char *str;
if (dummy->ai_family == AF_INET) {
str = (char*)malloc(INET_ADDRSTRLEN);
struct sockaddr_in *addr = (struct sockaddr_in*)dummy->ai_addr;
if (inet_ntop(AF_INET,&addr->sin_addr,str,INET_ADDRSTRLEN) == NULL) {
printf("inet_ntop error: %s\n",strerror(errno));
exit(1);
}
printf("using IP: %s Port: %d\n",str,ntohs(addr->sin_port));
}else if (dummy->ai_family == AF_INET6) {
str = (char*)malloc(INET6_ADDRSTRLEN);
struct sockaddr_in6 *addr = (struct sockaddr_in6*)dummy->ai_addr;
printf("using IP: %s Port: %d\n",inet_ntop(AF_INET6,&addr->sin6_addr,str,INET6_ADDRSTRLEN),ntohs(addr->sin6_port));
}else {
printf("unknown error\n");
continue;
}
free(str);
printf("------------------------------------\n\n\n");
}
freeaddrinfo(res);
return 0;
}
服務端程式碼:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/wait.h>
#include <time.h>
#define LISTENQ 100
#define BUFSIZE 4096
void sig_child(int signo) {
int ppid;
while ((ppid = waitpid(-1,NULL,WNOHANG)) > 0) {
printf("child process id %d terminated\n",ppid);
}
return;
}
void server_echo(int sockfd) {
char str[BUFSIZE];
time_t t = time(NULL);
strftime(str,BUFSIZE,"%Y %x %X",localtime(&t));
size_t len = strlen(str);
str[len] = '\n';
str[len + 1] = '\0';
if (write(sockfd,str,strlen(str)) != strlen(str)) {
printf("write error: %s\n",strerror(errno));
exit(1);
}
}
int main(int argc,char **argv) {
if (argc != 2) {
printf("please add <services name>\n");
exit(1);
}
struct addrinfo hints;
bzero(&hints,sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo* results;
int err;
if ((err = getaddrinfo(NULL,argv[1],&hints,&results)) != 0) {
printf("getaddrinfo error: %s\n",gai_strerror(err));
exit(1);
}
struct addrinfo* dummy = results;
int sockfd;
const int on = 1;
for (; dummy != NULL; dummy = dummy->ai_next) {
if ((sockfd = socket(dummy->ai_family,dummy->ai_socktype,dummy->ai_protocol)) < 0) {
continue;
}
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) < 0) {
printf("setsockopt error: %s\n",strerror(errno));
exit(1);
}
if (bind(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) {
break;
}
}
if (dummy == NULL) {
printf("all failed\n");
exit(1);
}
freeaddrinfo(results);
if (listen(sockfd,LISTENQ) < 0) {
printf("listen error: %s\n",strerror(errno));
exit(1);
}
if (signal(SIGCHLD,sig_child) == SIG_ERR) {
printf("signal error: %s\n",strerror(errno));
exit(1);
}
int connfd;
int ppid;
for (; ;) {
if ((connfd = accept(sockfd,NULL,NULL)) < 0) {
if (errno == EINTR) {
continue;
}
printf("accept error: %s\n",strerror(errno));
exit(1);
}
if ((ppid = fork()) < 0) {
printf("fork error: %s\n",strerror(errno));
exit(1);
}else if (ppid == 0) {
close(sockfd);
server_echo(connfd);
close(connfd);
exit(0);
}
close(connfd);
}
return 0;
}
客戶端程式碼:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#define BUFSIZE 4096
int main(int argc,char** argv) {
if (argc != 3) {
printf("please add <hostname/ip address> <service name>\n");
exit(1);
}
struct addrinfo hints;
bzero(&hints,sizeof(struct addrinfo));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
struct addrinfo* results;
int err;
if ((err = getaddrinfo(argv[1],argv[2],&hints,&results)) != 0) {
printf("getaddrinfo error: %s\n",gai_strerror(err));
exit(1);
}
struct addrinfo* dummy = results;
int sockfd;
for (; dummy != NULL; dummy = dummy->ai_next) {
if ((sockfd = socket(dummy->ai_family,dummy->ai_socktype,0)) < 0) {
continue;
}
if (dummy->ai_family == AF_INET) {
if (connect(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) {
break;
}
}else if (dummy->ai_family == AF_INET6) {
if (connect(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) {
break;
}
}else {
printf("unknown error\n");
exit(1);
}
}
if (dummy == NULL) {
printf("all connect failed\n");
exit(1);
}
char recv[BUFSIZE];
int n;
while ((n = read(sockfd,recv,BUFSIZE)) > 0) {
if (write(STDOUT_FILENO,recv,n) != n) {
printf("write error: %s\n",strerror(errno));
exit(1);
}
}
return 0;
}
相關文章
- serverless Error: getaddrinfo ENOTFOUND Function.doRequestServerErrorFunction
- svelte 執行報錯 getaddrinfo ENOTFOUND localhostlocalhost
- npm run dev 報錯:getaddrinfo ENOTFOUND localhost和解決方法NPMdevlocalhost
- SAP BTP MTA 應用的應用場景
- 棧的應用
- DirectSound的應用
- 包的應用
- set 的應用
- QlikView的應用View
- PCMCIA的應用
- Decorator 的應用
- 反射的應用反射
- 2.3 應用程式容器中的應用程式概述
- golang RPC 應用(1) :net/rpc的應用GolangRPC
- Windbg在應用層除錯漏洞時的應用除錯
- 基於應用程度的系統應用優化優化
- java的應用1Java
- java的應用2Java
- Promise的基本應用Promise
- Service Worker的應用
- python的應用Python
- 表單的應用
- Calendar 類的應用
- string 的應用
- Mysql profile 的應用MySql
- 字典樹的應用
- 應用卡的原因
- js/jquery的應用JSjQuery
- requestWindowFeature()的應用
- 框架應用的思考框架
- 理想的應用框架框架
- Canvas類的應用Canvas
- Java反射的應用Java反射
- 維模型的應用模型
- ORACLE 命令的應用Oracle
- 框架應用的利弊框架
- Git的基本應用Git
- 實用的位運算應用