Python中的UDP套接字编程

时间:2016-02-13 07:49:55

标签: python sockets server udp client

我正在尝试实现一个程序,该程序将使UDP服务器能够发送客户端请求的文件,并在特定目录中发送文件后对其进行日志记录。

任何人都可以指导我使用Code发送文件并在Python中记录它吗? 此外,我们需要以10 KB的块和最后的$发送数据,以宣布数据已完成。如果我尝试运行服务器端代码:这是我得到的错误:

Error message

任何帮助表示赞赏。提前致谢。

服务器端:

import socket
import threading
import os

def RetrFile(name, sock):
    filename = sock.recv(1024)
    if os.path.isfile(filename):
        sock.send("EXISTS " + str(os.path.getsize(filename)))
        userResponse = sock.recv(1024)
        if userResponse[:2] == 'OK':
            with open(filename, 'rb') as f:
                bytesToSend = f.read(1024)
                sock.send(bytesToSend)
                while bytesToSend != "":
                    bytesToSend = f.read(1024)
                    sock.send(bytesToSend)
    else:
        sock.send("ERR ")
    sock.close()

def Main():
    host = '192.168.0.24'
    port = 9090

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.bind((host,port))

    s.listen(5)

    print("Server Started.")
    while True:
        c, addr = s.accept()
        print("client connedted ip:<" + str(addr) + ">")
        t = threading.Thread(target=RetrFile, args=("RetrThread", c))
        t.start()

    s.close()

if __name__ == '__main__':
    Main()

客户端:

import socket

def Main():
    host = '192.168.0.24'
    port = 9090

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect((host, port))
    print("connected")

    filename = raw_input("Filename? -> ")
    if filename != 'q':
        s.send(filename)
        data = s.recv(1024)
        if data[:6] == 'EXISTS':
            filesize = long(data[6:])
            message = raw_input("File exists, " + str(filesize) + "Bytes, download? (Y/N)? -> ")
            if message == 'Y':
                s.send("OK")
                f = open('new_' + filename, 'wb')
                data = s.recv(1024)
                totalRecv = len(data)
                f.write(data)
                while totalRecv < filesize:
                    data = s.recv(1024)
                    totalRecv += len(data)
                    f.write(data)
                    print ("{0:.2f}".format((totalRecv / float(filesize)) * 100) + "% Done")
                print("Download Complete!")
                f.close()
        else:
            print ("File Does Not Exist!")
    s.close()
if __name__ == '__main__':
    Main()

1 个答案:

答案 0 :(得分:2)

虽然您想使用UDP,但所使用的调用更符合基于TCP的通信。如果您只是更改客户端和服务器中的以下行,这将在TCP

上正常工作

来自:

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

在服务器和客户端。

对于基于UDP的通信,只需要bind和recv。对TCP进行调用是为了接受服务器端的连接。类似地,在客户端,不需要连接调用,如果要设置源端口,然后是sendto,则绑定。对于服务器端来说是这样的

Server.py

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
#s.listen(5)

print("Server Started.")
while True:
    #c, addr = s.accept()
    data, client_addr = s.recvfrom(1024)

另请注意,服务器需要知道发送给客户端的内容,因此在线程中,如果需要并发服务器,则需要维护每个client_addr的状态。另一种方法是使用TFTP样式方法,作为响应的一部分,您发送不同的端口号以联系基于UDP的服务器,以便主端口可以返回到接收更多请求。此外,所有发送呼叫都必须转为必须指定客户端地址的sendto呼叫。

同样在客户端,你需要的东西如下(我已经评论了下面的TCP风格部分)

host = '127.0.0.1'
port = 9090

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server = (host, port)
#s.connect((host, port))
#print("connected")

filename = raw_input("Filename? -> ")
if filename != 'q':
    s.sendto(filename, server)
    data,server = s.recvfrom(1024)

通过一些修改,我能够在我的系统上传输你的文件。