6

最近,我设法在我的 PC 和 Raspberry Pi 上创建了套接字,以实现两个设备之间的通信。目前,客户端能够自动向服务器发送消息。我想知道,是否可以修改脚本以发送 tcp 数据包而不是纯文本消息,因为我非常希望将来使用我的 PC 来控制树莓派,而无需 ssh/etc。

我看过一些示例,但由于我在编写自己的脚本/代码方面没有太多经验,所以我不太确定如何去做。如果有人可以通过解释和一些示例(如果可能)引导我朝着正确的方向前进,我将不胜感激。

无论如何,这是我目前正在运行的服务器/客户端脚本:

客户:

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

2 回答 2

5

socket.socket(socket.AF_INET, socket.SOCK_STREAM)已经创建了一个在两台机器之间提供可靠字节流的连接。这使用 TCP,它位于 IP 和以太网之上。后两者是基于包的,而 TCP 在其上创建连续字节流。它还添加了一些错误检查和纠错功能,因此非常可靠。

老实说,我不明白你想用你所谓的“发送数据包”来实现什么。您不想做的是自己创建 TCP 的实现,因为这是一项不平凡的任务,因此发送 RAW 数据包已被淘汰。一般来说,即使使用 TCP 也已经是比较低级的了,除非真的有必要,否则应该避免使用。

使用例如ZeroMQ,您将获得一个为您完成所有传输的基于消息的接口。它在 TCP(或其他传输)之上执行此操作,并为例如断开连接添加更多纠错。在那里,你也有类似“数据包”的东西,但它们与需要多少 TCP 或 IP 数据包才能在下面发送它无关。如果您不想实现特定协议,我建议您使用此框架而不是低级 TCP 套接字。

另一个简单的替代方法是使用 HTTP,在 Python 中也有现有的代码。缺点是总是一方发起一些通信,另一方只回复。如果你想要某种主动通知,你要么必须投票,要么使用延迟回答等技巧。

于 2014-06-19T05:46:56.473 回答
1

您已经在发送数据包——这些数据包恰好包含文本数据。尝试查看标准库中的 pickle 和pyro

于 2013-07-06T06:56:30.200 回答