简体   繁体   中英

UDP Socket Programming in Python

I am trying to implement a program which will enable an UDP server to send file requested by client and make a log of it after the file is sent in a particular directory.

Can anyone please guide me with Code to send file and make log of it in Python? also, we need to send data in chunks of 10 KB and $ at the end to announce that data is finished. If I try to run server side code: here is the error I am getting:

Error message

any help appreciated. Thanks in Advance.

Server Side :

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

Client Side:

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

Although you want to use UDP the calls used are more in line for TCP based communication. If you simply change the following line in the client and the server this will work fine albeit over TCP

from:

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

to

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

in both server and client.

For UDP based communication one just needs bind and recv. Making a call to accept is in case of TCP for the purpose of accepting connection on the server side. Similarly on the client side there is no connection call required, bind if you want to set the source port followed by sendto. Something like this for the server side

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)

Also note that server needs to know what has been sent to a client so within thread you need to maintain states per client_addr if you expect concurrent server. The other alternative is to use TFTP style approach where as part of response you send a different port number to contact the UDP based server on so that the main port can then return back to receiving more requests. Also all send calls will have to turn into sendto calls where the client address must be specified.

Similarly on the client side you'll need something as below ( I have commented the TCP style portion below)

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)

With a bit of modification I was able to transmit your file over on my system.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM