Демультиплексирование сокета UDP на порту сервера - PullRequest
1 голос
/ 02 апреля 2019

Демультиплексирование сокета TCP на порту сервера (который прослушивает несколько соединений TCP) происходит с помощью отдельного дескриптора сокета, созданного для каждого установленного соединения TCP (несмотря на вызов accept ()), а дескриптор сокета тесно связан с кортежем [ IP-адрес источника, порт-источник, IP-адрес назначения, IP-адрес назначения ].По этому установленному соединению мы можем использовать протоколы приложений высокого уровня, такие как HTTP, FTP, SSH и т. Д.,

Но в случае UDP не устанавливается сеанс / соединение между узлами.Сервер, ожидающий на конкретном порту, получает сообщение от любого клиента.IP-адрес клиента и номер порта известны после получения сообщения (заполняется в структуре адреса сокета).Из структуры адреса сообщения могут быть демультиплексированы и переданы соответствующим приложениям.

Через порт сервера, если я хочу установить подключенный сеанс через UDP [как кортеж, упомянутый в случае TCP], чтобы обеспечить связь междусервер и клиент (между определенным портом на сервере и клиенте) могут быть демультиплексированы перед приемом сообщения (не выводя его из структуры адреса сокета), так что протоколы более высокого уровня могут работать как на TCP (конечно, протоколы более высокого уровня, такие как DTLS, заботятсянадежности)

Ниже приведен код для UDP-сервера (используя API connect () для поддержания соединения с сокетом UDP) и UDP-клиента

// server program for udp connection 
#include <stdio.h> 
#include <strings.h> 
#include <sys/types.h> 
#include <arpa/inet.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <stdio.h> 
#include <stdlib.h>
#include <string.h>

#define PORT 5000 
#define MAXLINE 1000 

//logical thread num
static unsigned int threadnum = 0;

struct pass_info {
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    unsigned int threadnum;
};

char *message = "Hello Client"; 

void* connection_handle(void *info) {
    int fd = 0;
    char buffer[100];
    int n = 0;
    const int on = 1;
    struct pass_info *pinfo = (struct pass_info*) info;

    printf("Executing thread : %d\n", pinfo->threadnum);

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0) {
        printf("Error socket!!!");
        return;
    }

    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));

    bind(fd, (const struct sockaddr *) &pinfo->server_addr, sizeof(struct sockaddr_in));
    connect(fd, (struct sockaddr *) &pinfo->client_addr, sizeof(struct sockaddr_in));

    while(1)
    {
        n = recv(fd, buffer, sizeof(buffer), 0);
        if (n < 0)
        {
            printf("receive failed! in thread : %d", pinfo->threadnum);
            break;
        }

        buffer[n] = '\0'; 
        printf("Thread num %d: Recv message - %s\n", pinfo->threadnum, buffer);

        n = send(fd, message, sizeof(message), 0);
        if (n < 0)
        {
            printf("send failed! in thread : %d", pinfo->threadnum);
            break;
        }
    }

    free(info);

    return NULL;
}

int main() 
{ 
    char buffer[100]; 
    int listenfd, len, sockfd; 
    const int on = 1;
    struct sockaddr_in servaddr, cliaddr; 
    bzero(&servaddr, sizeof(servaddr)); 
    struct pass_info *info;
    pthread_t tid;

    // Create a UDP Socket 
    listenfd = socket(AF_INET, SOCK_DGRAM, 0);       
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(PORT); 
    servaddr.sin_family = AF_INET; 

    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void*) &on, (socklen_t) sizeof(on));
    // bind server address to socket descriptor 
    bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); 

    while (1)
    {
        //receive the datagram 
        len = sizeof(cliaddr); 
        int n = recvfrom(listenfd, buffer, sizeof(buffer), 
                0, (struct sockaddr*)&cliaddr,&len); //receive message from server 
        buffer[n] = '\0'; 
        printf("Main thread: Recv message - %s\n", buffer); 

        n = sendto(listenfd, message, MAXLINE, 0, (struct sockaddr*)&cliaddr, sizeof(cliaddr)); 

        info = (struct pass_info*) malloc (sizeof(struct pass_info));
        memcpy(&info->server_addr, &servaddr, sizeof(struct sockaddr_in));
        memcpy(&info->client_addr, &cliaddr, sizeof(struct sockaddr_in));
        threadnum++;

        info->threadnum = threadnum;
        if (pthread_create(&tid, NULL, connection_handle, info) != 0) {
            perror("pthread_create");
            exit(-1);
        }
    }
} 

// udp client  program 
#include <stdio.h> 
#include <strings.h> 
#include <sys/types.h> 
#include <arpa/inet.h> 
#include <sys/socket.h> 
#include<netinet/in.h> 
#include<unistd.h> 
#include<stdlib.h> 

#define PORT 5000 
#define MAXLINE 1000 

int main() 
{ 
    char buffer[100]; 
    char *message = "Hello Server"; 
    int sockfd, n; 
    struct sockaddr_in servaddr, cliaddr; 
    int len = 0;

    // clear servaddr 
    bzero(&servaddr, sizeof(servaddr)); 
    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    servaddr.sin_port = htons(PORT); 
    servaddr.sin_family = AF_INET; 

    // create datagram socket 
    sockfd = socket(AF_INET, SOCK_DGRAM, 0); 

    while(1)
    {
        sleep(3);
        sendto(sockfd, message, MAXLINE, 0, (struct sockaddr*)&servaddr, sizeof(servaddr)); 

        // waiting for response 
        recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&cliaddr, &len); 
        puts(buffer); 

    }
} 

Запросы:

  1. Будет ли это правильным способом демультиплексирования на уровне сокета UDP

  2. Сервер прослушивает любые UDP-пакеты от клиента.как только он получает сообщение, создается новый дескриптор сокета и вызывается API connect (), так что IP-адрес клиента, порт регистрируется с помощью этого вновь созданного дескриптора сокета, и с этого момента вновь созданный дескриптор сокета будет использоваться для отправки и получения сообщений.на конкретный клиент IP-адрес и порт.Является ли это надежным методом

  3. Существуют ли другие хорошо известные методы для использования протоколов более высокого уровня (протоколы, поддерживающие надежность, такие как DTLS) по UDP

...