使用TCP套接字发送/接收数据包

int*_*ied 6 python sockets tcp client-server packet

最近,我设法在我的PC和Raspberry Pi上创建套接字,以实现两个设备之间的通信.目前,客户端能够自动向服务器发送消息.我想知道,如果有可能修改脚本来发送tcp数据包而不是纯文本消息,因为我非常希望将来使用我的PC来控制覆盆子pi,而不需要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()
Run Code Online (Sandbox Code Playgroud)

服务器:

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()
Run Code Online (Sandbox Code Playgroud)

Ulr*_*rdt 5

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

老实说,我不理解您所谓的“发送数据包”想要实现的目标。您不想做的是自己创建TCP的实现,因为这是一项艰巨的任务,因此发送RAW数据包的工作量很大。通常,即使使用TCP,也已经处于较低水平,除非真正必要,否则应避免使用。

使用例如ZeroMQ,您将获得一个基于消息的接口,可以为您完成所有传输。它在TCP(或其他传输)之上执行此操作,并为例如断开连接增加了更多的错误纠正。在那里,您还拥有类似“数据包”的内容,但是这些数据包与在下面发送数据包所需的TCP或IP数据包无关。如果您不想实现特定的协议,建议您使用此框架而不是低级TCP套接字。

另一个简单的选择是使用HTTP,在Python中也已有代码。不利之处在于,总是一方发起某种沟通,而另一方只做出回应。如果您想要某种形式的主动通知,则必须进行轮询或使用诸如延迟回答之类的黑客手段。


Ste*_*nes 1

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