2011-07-24 19 views
7

Estoy tratando de usar conectores de dominio UNIX para comunicarme entre un programa en C y un script de Python. La secuencia de comandos Python envía datos a través de sockets de dominio UNIX al programa C.C y Python: comunicación con conectores

Este es el código pertinente de mi programa C:

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/un.h> 
#include <sys/types.h> 
#include <sys/socket.h>  
#define UNIX_PATH_MAX 100 

int main(void) 
{ 
struct sockaddr_un address; 
int socket_fd, connection_fd; 
socklen_t address_length; 
pid_t child; 

socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); 
if (socket_fd < 0){ 
    printf("socket() failed\n"); 
    return 1; 
} 

unlink("/tmp/demo_socket"); 
memset(&address, 0, sizeof(struct sockaddr_un)); 

address.sun_family = AF_UNIX; 
snprintf(address.sun_path, UNIX_PATH_MAX, "/tmp/demo_socket"); 

if (bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0) { 
    printf("bind() failed\n"); 
    return 1; 
} 
if(listen(socket_fd, 5) != 0) { 
    printf("listen() failed\n"); 
    return 1; 
} 

//----------------WHILE LOOP-----------------------> 
while((connection_fd = accept(socket_fd, 
          (struct sockaddr *) &address, 
          &address_length)) > -1) 
{ 
. 
. 
.(doesn't get any further than this) 

Este es el script en Python que estoy utilizando para enviar un mensaje a la toma:

import socket 

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 
s.connect("/tmp/demo_socket") 
print "Sending..." 
s.send("Hello world") 
x = s.recv(1024) 
print x 
s.close() 

El script en Python falla con el error "Tubo roto". El programa C nunca ingresa al ciclo while porque la función accept() falla y devuelve '-1'.

¿Por qué está aceptando accept()? ¿Y qué puedo hacer para que tenga éxito?

+0

Imprime 'errno' (o mejor:' strerror (Error) ') en el código C cuando acepte falla. Esa y la página de manual deberían decirle al menos parte de la respuesta. – Mat

+0

No se produce el error "Argumento no válido". –

Respuesta

2

En cuanto a an example I found, parece que la longitud que pase bind no debe contar los nulos de terminación o relleno en el sockaddr_un.

Probar:

size_t addrlen; 
const char* sockname = "/tmp/demo_socket"; 

/* ... */ 

address.sun_family = AF_UNIX; 
snprintf(address.sun_path, UNIX_PATH_MAX, sockname); 
addrlen = sizeof(address.sun_family) + strlen(sockname); 

if (bind(socket_fd, (struct sockaddr *) &address, addrlen) != 0) { 
    printf("bind() failed\n"); 
    return 1; 
} 

P. S. Debido a esto, no necesita la llamada memset.

2

IIRC, address_length debe inicializarse al tamaño de sockaddr_un antes de la llamada accept(). Durante la llamada, se carga con la longitud real de la dirección par que se introduce en address.

Rgds, Martin

+0

Err ... uy, sí. ¡Gracias! –

+0

¡Brillante! Después de leer su sugerencia, y un poco de google, se me ocurrió una solución configurando: address_length = sizeof (address); antes de mi llamada de accept(). ¡Gracias! –

Cuestiones relacionadas