====== تابع ()socket ======
از تابع ()socket برای دریافت یک file descriptor جهت ارتباط با شبکه یا پروسس های دیگر، استفاده میشود.
// man 2 socket
#include
#include
sockfd = socket(int socket_family, int socket_type, int protocol);
بهتر است تمام ورودی های تابع ()socket از طریق [[getaddrinfo]] آماده شود.
درواقع domain همان rp->ai_family و type همان rp->ai_socktype و protocol همان rp->ai_protocol است.
باید تک تک استراکچر های linked-listی که [[getaddrinfo]] برگردانده بررسی شود تا بالاخره بتوانیم هم از طریق تابع ()socket یک file descriptor بگیریم هم از طریق [[bind]] به port متصل شویم.
مثال برای گرفتن file descriptor توسط تابع ()socket با کنترل تک تک استراکچرهای linked-list آماده شده توسط [[getaddrinfo]] :
// socket.c
// gcc -std=c99 -Wall -Wextra -Werror -pedantic -o socket socket.c
#define _POSIX_C_SOURCE 200112L
#include
#include
#include
#include
#include
#include
#include
#include
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
#define PORT "3440"
int main()
{
int sockfd, errcode;
struct addrinfo hints, *res, *rp;
char *ipver, ipstr[INET6_ADDRSTRLEN];
void *addr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
errcode = getaddrinfo(NULL, PORT, &hints, &res);
if (errcode != 0) {
fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(errcode));
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) {
handle_error("socket() error");
continue;
}
if (rp->ai_family == AF_INET) {
ipver = "IPv4";
addr = &(((struct sockaddr_in*)(rp->ai_addr))->sin_addr);
} else {
ipver = "IPv6";
addr = &(((struct sockaddr_in6*)(rp->ai_addr))->sin6_addr);
}
inet_ntop(rp->ai_family, addr, ipstr, sizeof ipstr);
fprintf(stdout, "I got an %s socket for %s = %d\n", ipver, ipstr, sockfd);
close(sockfd);
}
freeaddrinfo(res);
return 0;
}
خروجی
I got an IPv4 socket for 0.0.0.0 = 3
I got an IPv6 socket for :: = 3