ابزار کاربر

ابزار سایت


socket-programming:accept

این یک نگارش قدیمی از این مطلب است!


تابع ()accept

بعد از فراخوانی 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
socket-programming/accept.1718657962.txt.gz · آخرین ویرایش: 2024/06/18 00:29 توسط pejman

به جز مواردی که ذکر می‌شود، مابقی محتویات ویکی تحت مجوز زیر می‌باشند: Public Domain
Public Domain Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki