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

时间:2013-07-06 05:23:22

标签: 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()

服务器:

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

2 个答案:

答案 0 :(得分:4)

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

老实说,我不明白你想要通过什么来实现你想要达到的目标&#34;发送数据包&#34;。你不想做的是自己创建一个TCP的实现,因为这是一个非常重要的任务,所以发送RAW数据包就不行了。一般来说,即使使用TCP也已经相对较低,除非确实有必要,否则应该避免使用。

使用例如ZeroMQ你得到一个基于消息的界面,为你做所有的传输。它在TCP(或其他传输)之上这样做,并为例如增加了更多的纠错。断开。在那里,你还有类似&#34;数据包&#34;之类的内容,但这些内容与在下面发送它需要多少TCP或IP数据包无关。如果您不想实现特定协议,我建议您使用此框架而不是低级TCP套接字。

另一个简单的替代方法是使用HTTP,Python中也存在现有代码。缺点是它始终是一方启动一些沟通而另一方只回复。如果您想要某种有效的通知,您必须轮询或使用诸如延迟答案之类的黑客。

答案 1 :(得分:1)

您已经在发送数据包 - 这些数据包突然发生在当前包含文本数据。尝试在标准库中查看pickle并进入pyro