2013-07-06 34 views
5

Niedawno udało mi się stworzyć gniazda na moim komputerze i moim Raspberry Pi, aby umożliwić komunikację między obydwoma urządzeniami. Obecnie klient może automatycznie wysyłać wiadomości na serwer. Zastanawiam się, czy można zmodyfikować skrypty do wysyłania pakietów danych tcp zamiast czysto tekstowych, ponieważ bardzo chciałbym kontrolować raspberry pi używając mojego komputera w przyszłości, bez potrzeby ssh/etc.Wysyłanie/odbieranie pakietów z gniazdami TCP

Przyjrzałem się kilku przykładom, ale ponieważ nie mam dużego doświadczenia w pisaniu własnych skryptów/kodów, nie jestem pewien, jak to zrobić. Byłbym wdzięczny, gdyby ktoś mógł poprowadzić mnie we właściwym kierunku z wyjaśnieniami i przykładami, jeśli to możliwe.

Zresztą tutaj jest skrypt serwer/klient biegnę w tej chwili:

Klient:

import socket 
import sys 
import struct 
import time 

#main function 
if __name__ == "__main__": 

    if(len(sys.argv) < 2) : 
     print 'Usage : python client.py hostname' 
     sys.exit() 

    host = sys.argv[1] 
    port = 8888 

#create an INET, STREAMing socket 
try: 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
except socket.error: 
    print 'Failed to create socket' 
    sys.exit() 

print 'Socket Created' 

try: 
    remote_ip = socket.gethostbyname(host) 
    s.connect((host, port)) 

except socket.gaierror: 
    print 'Hostname could not be resolved. Exiting' 
    sys.exit() 

print 'Socket Connected to ' + host + ' on ip ' + remote_ip 

#Send some data to remote server 
message = "Test" 

try : 
    #Set the whole string 
    while True: 
     s.send(message) 
     print 'Message sent successfully' 
     time.sleep(1) 
     print 'Sending...' 
except socket.error: 
    #Send failed 
    print 'Send failed' 
    sys.exit() 

def recv_timeout(the_socket,timeout=2): 
    #make socket non blocking 
    the_socket.setblocking(0) 

    #total data partwise in an array 
    total_data=[]; 
    data=''; 

    #beginning time 
    begin=time.time() 
    while 1: 
     #if you got some data, then break after timeout 
     if total_data and time.time()-begin > timeout: 
      break 

     #if you got no data at all, wait a little longer, twice the timeout 
     elif time.time()-begin > timeout*2: 
      break 

     #recv something 
     try: 
      data = the_socket.recv(8192) 
      if data: 
       total_data.append(data) 
       #change the beginning time for measurement 
       begin=time.time() 
      else: 
       #sleep for sometime to indicate a gap 
       time.sleep(0.1) 
     except: 
      pass 

    #join all parts to make final string 
    return ''.join(total_data) 

#get reply and print 
print recv_timeout(s) 

s.close() 

Serwer:

import socket 
import sys 
from thread import * 

HOST = '' # Symbolic name meaning all available interfaces 
PORT = 8888 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
print 'Socket created' 

try: 
    s.bind((HOST, PORT)) 
except socket.error , msg: 
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] 
    sys.exit() 

print 'Socket bind complete' 

s.listen(10) 
print 'Socket now listening' 

#Function for handling connections 
def clientthread(conn): 
    #Sending message to connected client 
    conn.send('Welcome to the server. Receving Data...\n') #send only takes string 

    #infinite loop so that function do not terminate and thread do not end. 
    while True: 

     #Receiving from client 
     data = conn.recv(1024) 
     reply = 'Message Received at the server!\n' 
     print data 
     if not data: 
      break 

     conn.sendall(reply) 

    conn.close() 

#now keep talking with the client 
while 1: 
    #wait to accept a connection 
    conn, addr = s.accept() 
    print 'Connected with ' + addr[0] + ':' + str(addr[1]) 

    #start new thread 
    start_new_thread(clientthread ,(conn,)) 

s.close() 

Odpowiedz

0

Jesteś już wysyłanie pakietów danych - tych juts pakietów w danym momencie zawiera dane tekstowe. Spróbuj zagłębić się w standardowych bibliotekach i w pyro.

+0

Czytałem gniazda RAW oraz sposób wysyłania/odbierania pakietów RAW w TCP/IP i wymagałoby ręcznego określenia nagłówków tcp i ip w skrypcie. Czy byłby to lepszy sposób wysyłania pakietów do raspberry pi, aby kontrolować niektóre z jego funkcji? Niestety, jak wspomniałem, nie mam dużego doświadczenia z gniazdkami i pakietami. Skrypty, które używam, są standardowymi gniazdami, a ładunek "wiadomość" jest przesyłany przez TCP, czy możliwe jest zmodyfikowanie części skryptu w celu wysyłania pakietów (nie jako danych tekstowych) do wykonania pracy? – intensified

+0

Czy obsługa gniazda socket.error byłaby jedynym sposobem sprawdzenia błędów w wysyłanych danych? czy jest jakiś inny sposób, w jaki moglibyśmy dokonać sprawdzenia błędu, na przykład gdy dane otrzymane na serwerze, wykonaliby kontrolę nadmiarową, aby upewnić się, że nie ma danych utraconych podczas transmisji? – intensified

3

socket.socket(socket.AF_INET, socket.SOCK_STREAM) już tworzy połączenie zapewniające niezawodny strumień bajtów między dwoma komputerami. Używa TCP, który jest nad IP i Ethernet. Te dwa ostatnie są oparte na pakietach, podczas gdy TCP tworzy strumień ciągłych bajtów na wierzchu. Dodaje także pewne sprawdzanie błędów i korekcję błędów, więc jest całkiem niezawodny.

Szczerze nie rozumiem, co chcesz osiągnąć za pomocą tego, co nazywasz "wysyłaniem pakietów". To, czego nie chcesz robić, to samodzielne tworzenie implementacji TCP, ponieważ nie jest to łatwe zadanie, więc wysyłanie pakietów RAW jest niemożliwe. Ogólnie rzecz biorąc, nawet używanie TCP jest już względnie niskiego poziomu i powinno się go unikać, chyba że jest to naprawdę konieczne.

Stosując np. ZeroMQ otrzymujesz interfejs oparty na komunikatach, który wykonuje całą transmisję dla ciebie. Robi to ponad TCP (lub innymi transportami) i dodaje więcej korekcji błędów dla np. rozłącza się. Tam też masz coś takiego jak "pakiety", ale są one niezależne od tego, ile pakietów TCP lub IP było wymaganych do wysłania ich pod spodem. Jeśli nie chcesz zaimplementować określonego protokołu, proponuję użyć tego szkieletu zamiast niskonapięciowych gniazd TCP.

Inną prostą alternatywą jest użycie HTTP, dla którego istnieje również istniejący kod w Pythonie. Wadą jest to, że zawsze jedna strona inicjuje komunikację, a druga tylko odpowiada. Jeśli chcesz mieć jakieś aktywne powiadomienie, musisz sondować lub używać hacków takich jak opóźnianie odpowiedzi.