Демультиплексирование сокета 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);
}
}
Запросы:
Будет ли это правильным способом демультиплексирования на уровне сокета UDP
Сервер прослушивает любые UDP-пакеты от клиента.как только он получает сообщение, создается новый дескриптор сокета и вызывается API connect (), так что IP-адрес клиента, порт регистрируется с помощью этого вновь созданного дескриптора сокета, и с этого момента вновь созданный дескриптор сокета будет использоваться для отправки и получения сообщений.на конкретный клиент IP-адрес и порт.Является ли это надежным методом
Существуют ли другие хорошо известные методы для использования протоколов более высокого уровня (протоколы, поддерживающие надежность, такие как DTLS) по UDP