// client 連線到 server 的程式碼
// 透過 stream socket 連線到 www.example.com 的 port 80 (http)
struct addrinfo hints, *servinfo, *p;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // 設定 AF_INET6 表示強迫使用 IPv6
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo("www.example.com", "http", &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
break; // if we get here, we must have connected successfully
// 迴圈已經執行到 list 的最後,都無法連線
fprintf(stderr, "failed to connect\n");
freeaddrinfo(servinfo); // 釋放 servinfo 記憶體空間
// code for a server waiting for connections
// namely a stream socket on port 3490, on this host's IP
struct addrinfo hints, *servinfo, *p;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // 使用 AF_INET6 表示一定要用 IPv6
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // 使用我的 IP address
if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
break; // 若執行到這行,表示我們一定已經成功連線
// 整個迴圈執行完畢,到了 linked-list 結尾都無法成功綁定(bind)
fprintf(stderr, "failed to bind socket\n");
freeaddrinfo(servinfo); // 使用完畢時釋放這個資料結構的空間