Hay dos protocolos principales de capa de transporte para comunicarse entre hosts: TCP y UDP . La creación de un servidor/cliente TCP se discutió en una publicación anterior .
Requisito previo: creación de un servidor/cliente TCP
Teoría
En UDP, el cliente no forma una conexión con el servidor como en TCP y en su lugar solo envía un datagrama. De manera similar, el servidor no necesita aceptar una conexión y solo espera a que lleguen los datagramas. Los datagramas a su llegada contienen la dirección del remitente que el servidor utiliza para enviar datos al cliente correcto.
Todo el proceso se puede dividir en los siguientes pasos:
Servidor UDP:
- Cree un conector UDP.
- Vincule el socket a la dirección del servidor.
- Espere hasta que llegue el paquete de datagramas del cliente.
- Procese el paquete de datagramas y envíe una respuesta al cliente.
- Vuelva al Paso 3.
Cliente UDP:
- Cree un conector UDP.
- Envía un mensaje al servidor.
- Espere hasta que se reciba la respuesta del servidor.
- Procese la respuesta y vuelva al paso 2, si es necesario.
- Cierra el descriptor de socket y sal.
Funciones necesarias:
int socket(int domain, int type, int protocol) Creates an unbound socket in the specified domain. Returns socket file descriptor.
Argumentos:
dominio – Especifica el
tipo de dominio de comunicación (AF_INET para IPv4/ AF_INET6 para IPv6)
– Tipo de socket que se creará
(SOCK_STREAM para TCP/SOCK_DGRAM para UDP)
protocolo – Protocolo que utilizará el socket.
0 significa usar el protocolo predeterminado para la familia de direcciones.
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) Assigns address to the unbound socket.
Argumentos:
sockfd: descriptor de archivo de un socket que se
vinculará. addr: estructura en la que se especifica la dirección a la que se vinculará
. addrlen: tamaño de la estructura addr .
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) Send a message on the socket
Argumentos:
sockfd: descriptor de archivo del socket
buf: búfer de la aplicación que contiene los datos que se enviarán
len: tamaño de las banderas del búfer de la aplicación buf : OR bit a bit de las banderas para modificar el comportamiento del socket dest_addr: estructura que contiene la dirección del destino addrlen: tamaño de dest_addr estructura
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) Receive a message from the socket.
Argumentos:
sockfd: descriptor de archivo del socket
buf: búfer de la aplicación en el que recibir datos
len: tamaño de las banderas del búfer de la aplicación buf : OR bit a bit de las banderas para modificar el comportamiento del socket src_addr: se devuelve la estructura que contiene la dirección de origen addrlen: variable en qué tamaño de se devuelve la estructura src_addr
int close(int fd) Close a file descriptor
Argumentos:
fd – Descriptor de archivo
En el siguiente código, se muestra el intercambio de un mensaje de saludo entre el servidor y el cliente para demostrar el modelo.
Nombre de archivo: UDPServer.c
C
// Server side implementation of UDP client-server model #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #define PORT 8080 #define MAXLINE 1024 // Driver code int main() { int sockfd; char buffer[MAXLINE]; char *hello = "Hello from server"; struct sockaddr_in servaddr, cliaddr; // Creating socket file descriptor if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket creation failed"); exit(EXIT_FAILURE); } memset(&servaddr, 0, sizeof(servaddr)); memset(&cliaddr, 0, sizeof(cliaddr)); // Filling server information servaddr.sin_family = AF_INET; // IPv4 servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(PORT); // Bind the socket with the server address if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) { perror("bind failed"); exit(EXIT_FAILURE); } int len, n; len = sizeof(cliaddr); //len is value/result n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len); buffer[n] = '\0'; printf("Client : %s\n", buffer); sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len); printf("Hello message sent.\n"); return 0; }
Nombre de archivo: UDPClient.c
C
// Client side implementation of UDP client-server model #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #define PORT 8080 #define MAXLINE 1024 // Driver code int main() { int sockfd; char buffer[MAXLINE]; char *hello = "Hello from client"; struct sockaddr_in servaddr; // Creating socket file descriptor if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket creation failed"); exit(EXIT_FAILURE); } memset(&servaddr, 0, sizeof(servaddr)); // Filling server information servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); servaddr.sin_addr.s_addr = INADDR_ANY; int n, len; sendto(sockfd, (const char *)hello, strlen(hello), MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr)); printf("Hello message sent.\n"); n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *) &servaddr, &len); buffer[n] = '\0'; printf("Server : %s\n", buffer); close(sockfd); return 0; }
Producción :
$ ./server Client : Hello from client Hello message sent.
$ ./client Hello message sent. Server : Hello from server