深入理解計算機系統(第三版)第十一章重要內容摘要
阿新 • • 發佈:2021-01-19
11.1客戶端-伺服器程式設計模型
11.2網路
11.3全球IP因特網
13.3.1 IP地址
11.3.2因特網域名
11.3.3因特網連線
11.4套接字介面
11.4.1套接字地址結構
11.4.2socket函式
11.4.3connect函式
11.4.4bind函式
11.4.5listen函式
11.4.6accept函式
11.4.7主機和服務的轉換
1.getaddrinfo函式
2.getnameinfo
11.4.8套接字介面的輔助函式
1.open_clientfd函式
/* $begin open_clientfd */ int open_clientfd(char *hostname, char *port) { int clientfd, rc; struct addrinfo hints, *listp, *p; /* Get a list of potential server addresses */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; /* Open a connection*/ hints.ai_flags = AI_NUMERICSERV; /* ... using a numeric port arg. */ hints.ai_flags |= AI_ADDRCONFIG; /* Recommended for connections */ if ((rc = getaddrinfo(hostname, port, &hints, &listp)) != 0) { fprintf(stderr, "getaddrinfo failed (%s:%s): %s\n", hostname, port, gai_strerror(rc));return -2; } /* Walk the list for one that we can successfully connect to */ for (p = listp; p; p = p->ai_next) { /* Create a socket descriptor */ if ((clientfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) continue; /* Socket failed, try the next */ /* Connect to the server */ if (connect(clientfd, p->ai_addr, p->ai_addrlen) != -1) break; /* Success */ if (close(clientfd) < 0) { /* Connect failed, try another */ //line:netp:openclientfd:closefd fprintf(stderr, "open_clientfd: close failed: %s\n", strerror(errno)); return -1; } } /* Clean up */ freeaddrinfo(listp); if (!p) /* All connects failed */ return -1; else /* The last connect succeeded */ return clientfd; } /* $end open_clientfd */
2.open_listenfd函式
/* $begin open_listenfd */ int open_listenfd(char *port) { struct addrinfo hints, *listp, *p; int listenfd, rc, optval=1; /* Get a list of potential server addresses */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_socktype = SOCK_STREAM; /* Accept connections */ hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* ... on any IP address */ hints.ai_flags |= AI_NUMERICSERV; /* ... using port number */ if ((rc = getaddrinfo(NULL, port, &hints, &listp)) != 0) { fprintf(stderr, "getaddrinfo failed (port %s): %s\n", port, gai_strerror(rc)); return -2; } /* Walk the list for one that we can bind to */ for (p = listp; p; p = p->ai_next) { /* Create a socket descriptor */ if ((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) continue; /* Socket failed, try the next */ /* Eliminates "Address already in use" error from bind */ setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, //line:netp:csapp:setsockopt (const void *)&optval , sizeof(int)); /* Bind the descriptor to the address */ if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break; /* Success */ if (close(listenfd) < 0) { /* Bind failed, try the next */ fprintf(stderr, "open_listenfd close failed: %s\n", strerror(errno)); return -1; } } /* Clean up */ freeaddrinfo(listp); if (!p) /* No address worked */ return -1; /* Make it a listening socket ready to accept connection requests */ if (listen(listenfd, LISTENQ) < 0) { close(listenfd); return -1; } return listenfd; }/* $end open_listenfd */