web-dev-qa-db-ja.com

TCPソケットを使用してパケットを送受信する

最近、PCとRaspberry Piにソケットを作成して、両方のデバイス間の通信を可能にしました。現在、クライアントはサーバーにメッセージを自動的に送信できます。将来、sshなどを使用せずにPCを使用してRaspberry Piを制御したいので、純粋なテキストメッセージの代わりにtcpデータパケットを送信するようにスクリプトを変更できるかどうか疑問に思いました。

いくつかの例を見てきましたが、自分でスクリプトやコードを書いた経験があまりないので、どうやってこれを行うのかよくわかりません。誰かが説明と可能であればいくつかの例で私を正しい方向に導くことができれば幸いです。

とにかくここに私が現在実行しているサーバー/クライアントスクリプトがあります:

クライアント:

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()

サーバ:

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()
6
intensified

socket.socket(socket.AF_INET, socket.SOCK_STREAM)は、2台のマシン間で信頼できるバイトストリームを提供する接続をすでに作成しています。これは、IPとイーサネットの上にあるTCPを使用します。後者の2つはパッケージベースですが、TCPはその上に連続バイトのストリームを作成します。また、エラーチェックとエラー訂正も追加されるため、かなり信頼性があります。

正直なところ、「パケット送信」と呼ばれるもので何を達成したいのかわかりません。 TCPの実装を自分で作成するのは簡単な作業ではないため、RAWパケットの送信は不要です。一般に、TCPの使用でさえ、すでに比較的低レベルであり、本当に必要な場合を除いて避ける必要があります。

使用例: ZeroMQを使用すると、すべての送信を行うメッセージベースのインターフェイスを利用できます。 TCP(または他のトランスポート)の上でこれを行い、たとえば次のエラー訂正を追加します。切断します。そこには「パケット」のようなものもありますが、それらは下に送信するために必要なTCPまたはIPパケットの数とは無関係です。特定のプロトコルを実装したくない場合は、低レベルのTCPソケットの代わりにこのフレームワークを使用することをお勧めします。

もう1つの簡単な代替方法は、HTTPを使用することです。HTTPには、Pythonに既存のコードもあります。欠点は、通信を開始するのは常に一方の側であり、もう一方の側は応答するだけであるということです。ある種のアクティブな通知が必要な場合は、ポーリングするか、回答を遅らせるなどのハックを使用する必要があります。

5
Ulrich Eckhardt

あなたはすでにデータパケットを送信しています-それらのパケットの突き出しには、現時点でテキストデータが含まれています。標準ライブラリのpickleと pyro を調べてみてください。

1
Steve Barnes