Tabla de contenido
En este artículo, exploraremos cómo utilizar socket en lenguaje C para implementar un sistema de mensajes TCP de envío asincrónico y de subprocesos múltiples. Aunque la biblioteca estándar de C no admite de forma nativa la programación asincrónica y de subprocesos múltiples, podemos usar la biblioteca y el socket de subprocesos POSIX (pthread) para lograr el objetivo.
conocimiento básico
TCP (Protocolo de control de transmisión) es un protocolo de comunicación basado en flujo de bytes, confiable y orientado a la conexión.
Socket es una interfaz de programación de red que permite a las aplicaciones enviar y recibir datos a través de la red.
La programación multiproceso es un método para ejecutar múltiples tareas simultáneamente, y cada tarea se ejecuta en un hilo separado.
La mensajería asincrónica es un modelo de programación en el que el remitente de un mensaje no necesita esperar a que el receptor procese el mensaje, puede regresar inmediatamente y continuar con otras tareas.
empezar a darse cuenta
Primero, debemos incluir los archivos de encabezado necesarios.
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>
Luego, definimos una función send_message
que será llamada en un nuevo hilo para enviar el mensaje.
void* send_message(void* arg)
{
char* message = (char*)arg;
int sock;
struct sockaddr_in server;
// Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
perror("Could not create socket");
return NULL;
}
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(8888);
// Connect to remote server
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0)
{
perror("Connect failed");
return NULL;
}
// Send some data
if (send(sock, message, strlen(message), 0) < 0)
{
perror("Send failed");
return NULL;
}
close(sock);
return NULL;
}
Esta send_message
función primero crea un socket y se conecta al servidor remoto. Luego, envía un mensaje y cierra el socket.
Ahora, podemos crear varios hilos en la función principal y cada hilo envía un mensaje.
int main()
{
// Array of messages to be sent
char* messages[] = {
"Hello", "from", "C"};
// Create a new thread for each message
pthread_t threads[sizeof(messages)/sizeof(char*)];
for (int i = 0; i < sizeof(messages)/sizeof(char*); i++)
{
if (pthread_create(&threads[i], NULL, send_message, messages[i]) < 0)
{
perror("Could not create thread");
return 1;
}
}
// Wait for all threads to finish
for (int i = 0; i < sizeof(threads)/sizeof(pthread_t); i++)
{
pthread_join(threads[i], NULL);
}
return 0;
}
En este código, creamos un nuevo hilo para cada mensaje que se enviará y pasamos send_message
la función como función del hilo. Luego, esperamos a que se completen todos los hilos.
Descripción de la función principal
1. función de enchufe
La función de socket se utiliza para crear un socket y devolver el descriptor de archivo del socket, que se <sys/socket.h>
define en el archivo de encabezado. Su prototipo de función es el siguiente:
int socket(int domain, int type, int protocol);
-
domain
: Este parámetro especifica la familia de protocolos (Protocol Family) utilizada. Las familias de protocolos comunes incluyen AF_INET (protocolo de red IPv4), AF_INET6 (protocolo de red IPv6), etc. -
type
: este parámetro especifica el tipo de servicio. Los tipos de servicios comunes incluyen SOCK_STREAM (que proporciona una transmisión de datos estable orientada a la conexión, es decir, el protocolo TCP), SOCK_DGRAM (que proporciona una transmisión de datos inestable sin conexión, es decir, el protocolo UDP), etc. -
protocol
: este parámetro generalmente se establece en 0, lo que permite que el sistematype
seleccione automáticamente el protocolo apropiado, como TCP o UDP.
Si la función de socket tiene éxito, devuelve un nuevo descriptor de socket; de lo contrario, devuelve -1 y establece errno en el número de error.
2. función pthread_create
La función pthread_create se utiliza para crear un nuevo hilo y permitir que el nuevo hilo ejecute la función especificada. Está <pthread.h>
definido en el archivo de encabezado. Su prototipo de función es el siguiente:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
-
thread
: Este es un parámetro de salida que devuelve el ID del hilo recién creado. -
attr
: Un puntero a una estructura de atributos de hilo, utilizado para establecer los atributos del nuevo hilo. Si se establece en NULL, se utilizan las propiedades predeterminadas. -
start_routine
: un puntero de función que apunta a la función que ejecutará el nuevo hilo. -
arg
: Un puntero alstart_routine
parámetro que se va a pasar.
Si la función pthread_create tiene éxito, devuelve 0; si falla, devuelve un código de error distinto de cero (tenga en cuenta que esta función no establece errno). El hilo recién creado start_routine
comienza a ejecutarse desde la dirección de la función y, una vez que start_routine
regresa, el hilo finalizará automáticamente.
conclusión
Este es un ejemplo simple del uso de sockets en C para implementar el envío asincrónico de subprocesos múltiples de mensajes TCP. Este es un ejemplo básico; el uso real puede requerir agregar código de manejo de errores y manejo de excepciones. Al mismo tiempo, debido a que el lenguaje C no tiene soporte integrado para subprocesos múltiples o asincrónicos, este método no es completamente asincrónico, pero podemos simular un comportamiento asincrónico mediante el uso de subprocesos múltiples.