بعد از فراخوانی تابع ()listen نوبت به فراخوانی تابع ()accept میرسد تا به ازای هر connection جدید یک file descriptor جدید برای خواندن و نوشتن در آن connection ایجاد کند و اطلاعات مربوط به connection جدید را در یک struct sockaddr_storage برگرداند ( که درواقع cast شده است به struct sockaddr ) :
#include <sys/types.h> #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
نکته : تابع ()accept از نوع blocking است.
مثال تابع ()accept در وضعیت dual-stack :
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> #define PORT "3450" #define BACKLOG 120 int main() { int status, sockfd, clientfd, sockopt; struct addrinfo hints, *res, *rp; struct sockaddr_storage clientaddr; socklen_t addrlen; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; status = getaddrinfo(NULL, PORT, &hints, &res); if (status != 0) { fprintf(stderr, "getaddrinfo() error: %s\n", gai_strerror(status)); exit(EXIT_FAILURE); } for (rp = res; rp != NULL; rp = rp->ai_next) { sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sockfd == -1) { perror("socket() error"); continue; } sockopt = 1; status = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); if (status == -1) { perror("setsockopt() error"); exit(EXIT_FAILURE); } sockopt = 0; status = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &sockopt, sizeof(sockopt)); if (status == -1) { perror("setsockopt() error"); exit(EXIT_FAILURE); } status = bind(sockfd, rp->ai_addr, rp->ai_addrlen); if (status == -1) { perror("bind() error"); continue; } break; } freeaddrinfo(res); if (rp == NULL) { fprintf(stderr, "Server: Failed to bind()\n"); exit(EXIT_FAILURE); } status = listen(sockfd, BACKLOG); if (status == -1) { perror("listen() error"); exit(EXIT_FAILURE); } printf("Server: waiting for connections...\n"); addrlen = sizeof(clientaddr); clientfd = accept(sockfd, (struct sockaddr*)&clientaddr, &addrlen); void *addr; char *ipver; char ipstr[INET6_ADDRSTRLEN]; struct sockaddr *sa = (struct sockaddr*)&clientaddr; if (sa->sa_family == AF_INET) { ipver = "IPv4"; addr = &(((struct sockaddr_in *)sa)->sin_addr); } else { ipver = "IPv6"; addr = &(((struct sockaddr_in6 *)sa)->sin6_addr); } inet_ntop(sa->sa_family, addr, ipstr, sizeof(ipstr)); printf("Server: Got an %s connection from %s\n", ipver, ipstr); close(clientfd); close(sockfd); return 0; }
کلاینت
telnet 127.0.0.1 3450
خروجی سرور
Server: waiting for connections... Server: Got an IPv6 connection from ::ffff:127.0.0.1