Почему accept() создает новый сокет?

#c #linux #sockets #network-programming

#c #linux #сокеты #сетевое программирование

Вопрос:

Это рисунок, демонстрирующий типичную модель клиент-сервер из интерфейса программирования Linux

введите описание изображения здесь

Это пример исходного кода для серверной части от geeksforgeeks

 #include <stdio.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#define MAX 80 
#define PORT 8080 
#define SA struct sockaddr 
  
// Function designed for a chat between client and server. 
void func(int sockfd) 
{ 
    // server's job
} 
  
// Driver function 
int main() 
{ 
    int sockfd, connfd, len; 
    struct sockaddr_in servaddr, cli; 
  
    // socket create and verification 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd == -1) { 
        printf("socket creation failed...n"); 
        exit(0); 
    } 
    else
        printf("Socket successfully created..n"); 
    bzero(amp;servaddr, sizeof(servaddr)); 
  
    // assign IP, PORT 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(PORT); 
  
    // Binding newly created socket to given IP and verification 
    if ((bind(sockfd, (SA*)amp;servaddr, sizeof(servaddr))) != 0) { 
        printf("socket bind failed...n"); 
        exit(0); 
    } 
    else
        printf("Socket successfully binded..n"); 
  
    // Now server is ready to listen and verification 
    if ((listen(sockfd, 5)) != 0) { 
        printf("Listen failed...n"); 
        exit(0); 
    } 
    else
        printf("Server listening..n"); 
    len = sizeof(cli); 
  
    // Accept the data packet from client and verification 
    connfd = accept(sockfd, (SA*)amp;cli, amp;len); 
    if (connfd < 0) { 
        printf("server acccept failed...n"); 
        exit(0); 
    } 
    else
        printf("server acccept the client...n"); 
  
    // Function for chatting between client and server 
    func(connfd); 
  
    // After chatting close the socket 
    close(sockfd); 
} 
 

В книге, о которой я упоминал выше, автор сказал

Ключевым моментом для понимания accept() является то, что он создает новый сокет, и именно этот новый сокет подключен к одноранговому сокету, который выполнил connect() .

В исходном коде сервера есть 2 сокета

  • sockfd , вывод socket()
  • connfd , вывод accept()

Почему серверная часть не используется sockfd для «общения» с клиентом, а создает новый сокет connfd , а затем «разговаривает» с клиентом, пока сокет уже существует?

Ответ №1:

Прослушивающий сокет можно использовать для приема нескольких подключений, каждое с разной парой удаленных IP / портов.

TCP-соединение определяется 4 значениями: IP-адрес источника, порт источника, IP-адрес назначения, порт назначения. Дескриптор сокета, возвращаемый с помощью accept , связан с таким соединением. В отличие от этого, прослушивающий сокет связан только с локальным IP и портом.

В этом конкретном примере кода он вызывается только accept один раз. Но это может быть сделано в цикле для обработки соединений с нескольких конечных точек. Обычно такой процесс будет иметь один поток, вызываемый accept в цикле. Затем, когда возвращается новый сокет accept , запускается новый поток для обработки этого соединения, в то время как основной поток вызывает accept снова.

Ответ №2:

К серверу может быть подключено несколько клиентов одновременно. Один дескриптор сокета не может представлять несколько соединений. Каждое соединение состоит из уникальной комбинации пар локальный одноранговый адрес / порт, поэтому серверу требуется отдельный дескриптор сокета для представления каждого из них.