¿Qué es la programación de sockets?
La programación de sockets es una forma de conectar dos Nodes en una red para comunicarse entre sí. Un socket (Node) escucha en un puerto particular en una IP, mientras que el otro socket se comunica con el otro para formar una conexión. El servidor forma el socket de escucha mientras el cliente se comunica con el servidor.
Diagrama de estado para el modelo de servidor y cliente
Etapas para servidor
1. Creación del zócalo:
int sockfd = socket(dominio, tipo, protocolo)
- sockfd: descriptor de socket, un número entero (como un identificador de archivo)
- dominio: entero, especifica el dominio de comunicación. Usamos AF_ LOCAL como se define en el estándar POSIX para la comunicación entre procesos en el mismo host. Para la comunicación entre procesos en diferentes hosts conectados por IPV4, usamos AF_INET y AF_I NET 6 para procesos conectados por IPV6.
- tipo: tipo de comunicación
SOCK_STREAM: TCP (confiable, orientado a la conexión)
SOCK_DGRAM: UDP (no confiable, sin conexión) - protocolo: Valor de protocolo para el Protocolo de Internet (IP), que es 0. Este es el mismo número que aparece en el campo de protocolo en el encabezado IP de un paquete. (Protocolos de hombre para más detalles)
2. Setsockopt: Esto ayuda en la manipulación de opciones para el socket al que hace referencia el descriptor de archivo sockfd. Esto es completamente opcional, pero ayuda a reutilizar la dirección y el puerto. Previene errores como: “dirección ya en uso”.
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
3. Vincular:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Después de la creación del socket, la función de vinculación vincula el socket a la dirección y el número de puerto especificados en addr (estructura de datos personalizada). En el código de ejemplo, vinculamos el servidor al host local, por lo que usamos INADDR_ANY para especificar la dirección IP.
4. Escucha:
int listen(int sockfd, int backlog);
Pone el socket del servidor en modo pasivo, donde espera a que el cliente se acerque al servidor para establecer una conexión. El backlog define la longitud máxima a la que puede crecer la cola de conexiones pendientes para sockfd. Si llega una solicitud de conexión cuando la cola está llena, el cliente puede recibir un error con una indicación de ECONNREFUSED.
5. Aceptar:
int new_socket= accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Extrae la primera solicitud de conexión en la cola de conexiones pendientes para el socket de escucha, sockfd, crea un nuevo socket conectado y devuelve un nuevo descriptor de archivo que hace referencia a ese socket. En este punto, se establece la conexión entre el cliente y el servidor, y están listos para transferir datos.
Etapas para Cliente
- Conexión de socket: exactamente igual que la creación del socket del servidor
- Conectar: la llamada al sistema connect() conecta el socket al que hace referencia el descriptor de archivo sockfd a la dirección especificada por addr. La dirección y el puerto del servidor se especifican en addr.
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Implementación
Aquí estamos intercambiando un mensaje de saludo entre el servidor y el cliente para demostrar el modelo cliente/servidor.
- Servidor.c
C
// Server side C/C++ program to demonstrate Socket // programming #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> #define PORT 8080 int main(int argc, char const* argv[]) { int server_fd, new_socket, valread; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); char buffer[1024] = { 0 }; char* hello = "Hello from server"; // Creating socket file descriptor if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // Forcefully attaching socket to the port 8080 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); // Forcefully attaching socket to the port 8080 if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } if ((new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0) { perror("accept"); exit(EXIT_FAILURE); } valread = read(new_socket, buffer, 1024); printf("%s\n", buffer); send(new_socket, hello, strlen(hello), 0); printf("Hello message sent\n"); // closing the connected socket close(new_socket); // closing the listening socket shutdown(server_fd, SHUT_RDWR); return 0; }
- cliente.c
C
// Client side C/C++ program to demonstrate Socket // programming #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> #define PORT 8080 int main(int argc, char const* argv[]) { int sock = 0, valread, client_fd; struct sockaddr_in serv_addr; char* hello = "Hello from client"; char buffer[1024] = { 0 }; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("\n Socket creation error \n"); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); // Convert IPv4 and IPv6 addresses from text to binary // form if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { printf( "\nInvalid address/ Address not supported \n"); return -1; } if ((client_fd = connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) < 0) { printf("\nConnection Failed \n"); return -1; } send(sock, hello, strlen(hello), 0); printf("Hello message sent\n"); valread = read(sock, buffer, 1024); printf("%s\n", buffer); // closing the connected socket close(client_fd); return 0; }
Compilando:
gcc client.c -o client gcc server.c -o server
Producción:
Client:Hello message sent Hello from server Server:Hello from client Hello message sent
Este artículo es una contribución de Akshat Sinha . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA