La historia general es que necesitaba comunicar una Fonera (la cuál no tiene muchos recursos) con un servidor central (RaspberryPi) que tiene toda la infraestructura desarrollada en Python. Para no complicarme la vida, hice un pequeño servidor en C para la Fonera y un cliente en Python para la Raspberry.
Este código corresponde a la Fonera, y lo podemos guardar como server.c (en Mega)
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#define MAXLINE 4096 /* buffer length */
#define SERV_PORT 10001 /* port */
#define LISTENQ 8 /* maximum number of client connections */
/* This function read a character from a buffer (fd) until it reads
the character (until), and it saves in (data). */
int read_until(int fd, char *data, char until) {
int len = 0;
char a[1];
int n;
do {
n = recv(fd, a, 1, 0);
if (n>0) // OK
data[len++] = a[0];
} while (a[0]!=until);
data[len] = '\0';
return len;
}
int main (int argc, char **argv) {
int listenfd, connfd, n;
socklen_t client_len;
char buf[MAXLINE];
struct sockaddr_in cliaddr, servaddr;
// Socket creation
listenfd = socket (AF_INET, SOCK_STREAM, 0);
// Preparing the socket address
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind (listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen (listenfd, LISTENQ);
printf("Server running! Waiting...\n");
while(1) {
client_len = sizeof(cliaddr);
connfd = accept (listenfd, (struct sockaddr *) &cliaddr, &client_len);
printf("Received request...\n");
read_until(connfd, buf, '\n');
printf("Received content: %s" , buf);
// Proccess the content
// ...
sleep(3); //Simulating process time
// Send response
send(connfd, buf, strlen(buf), 0);
// Close client connection
close(connfd);
} // And wait for another client
// Close listening socket
close (listenfd);
}
Lo compilamos para la Fonera y lo ejecutamos: (Compilando C/C++ para La Fonera (MIPS))
$ mips-linux-gcc server.c -o server
$ ./server
Ahora pasamos a crear el código en Python para guardarlo en la RaspberryPi como client.py (en Mega)
import socket
import sys
SERVER = '192.168.1.69' # Server IP or domain
PORT = 10001 # Server port
"""
This function read a character from a buffer (fd) until it reads
the character (until), and return the string.
"""
def read_until(fd, until):
to_ret = ''
try:
a = fd.recv(1)
while a[0] != until:
to_ret += a
a = fd.recv(1)
to_ret += a
except:
print "Error: Socket closed (or another thing!) :P"
return None
return to_ret;
def main():
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
server_address = (SERVER, PORT)
print 'Connecting to %s in port %s' % server_address
sock.connect(server_address)
try:
# Send message
message = 'request:variable\n'
print 'Sending: %s' % message
sock.sendall(message)
# Wait the response
data = read_until(sock, '\n')
print 'Received: %s' % data
finally:
print 'Closing socket'
sock.close()
if __name__ == '__main__':
main()
NOTA: En la dirección IP habría que poner la IP de la Fonera (servidor), en mi caso es la 192.168.1.69
Ya sólo tendríamos que ejecutar el cliente en la Raspberry con:
$ python client.py
En ese momento, el cliente enviará al servidor el mensaje (request:variable\n), el servidor simulará su procesamiento durante 3 segundos y devolverá la respuesta. En esta caso, la respuesta coincide con los datos recibidos, pero no tiene que ser así.
Referencias:
- http://www.cs.dartmouth.edu/~campbell/cs50/socketprogramming.html
- http://pymotw.com/2/socket/tcp.html
No hay comentarios:
Publicar un comentario