Python file transfer error w/ sockets - python

Here is my server.py:
import socket, atexit
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((socket.gethostname(), 8000))
server.listen(5)
(client,(ip,port))=server.accept()
command = raw_input('> ')
if command.rsplit(' ',1)[0] == 'write':
client.send(command.rsplit(' ',1)[2])
print 'Client # ', ip + ' '
data = client.recv(1024)
file = open(command.rsplit(' ',1)[1],'rb')
bytes = file.read(1024)
while(bytes):
client.send(bytes)
bytes = file.read(1024)
file.close()
client.close()
The client.py:
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('MY IP', 8000))
client.send("!")
name = client.recv(1024)
with open(name, 'wb') as file:
while True:
data = client.recv(1024)
if not data:
break
file.write(data)
file.close()
client.close()
The first data transmission in server.py is supposed to send the name of the file I want to the client.py. Where it says:
name = client.recv(1024)
in client.py, it is supposed to receive and make a file using that name. However, the server.py closes, causing the client.py to crash and not give output (host closed). If I open in IDLE to see the output, it doesn't work but nothing shows.

Your server.py needed tweaked;
import socket, atexit
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 8000))
server.listen(5)
(client,(ip,port))=server.accept()
command = raw_input('> ')
if command.split(' ')[0] == 'write':
client.send(command.split(' ')[2])
print 'Client # '+str(ip)+':'
data = client.recv(1024)
file = open(command.split(' ')[1],'rb')
bytes = file.read(1024)
while(bytes):
client.send(bytes)
bytes = file.read(1024)
file.close()
client.close()
The rsplit and trailing ,1's were causing the breaks.
Using the input write /Users/Namelessthehckr/Downloads/ucsgflmza.cs /Users/Namelessthehckr/Desktop/Test.txt, the file was successfully CP'd without error.

Related

Python UDP File Transfer

I'm creating a udp file transfer using python with a client (requests file from server), a server (receives request from client and passes it to the relevant worker) and worker1/worker2 (recieve request from server, if file exists, sends to server to pass back to client) and its all ran in docker containers with an ubuntu image*
Currently, when I type the name of the file I want in the client container, nothing works. I think the file name isn't actually being sent to the server but I can't figure out why at all. I was wondering if anyone can spot my mistake?
Server:
from fileinput import filename
import socket
import time
localIP = "127.0.0.1"
localPort = 50001
bufSize = 1024
msg = "Server is connecting..."
print(msg)
workerAddressPorts = [('127.0.0.1', 50002), ('127.0.0.1', 50003)]
# Create datagram sockets and bind to address and ip
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPServerSocket.bind((localIP, localPort))
print("Server is waiting for packet...")
while True:
bytesAddressPair = UDPServerSocket.recvfrom(bufSize)
clientBuf = bytesAddressPair[0]
clientAddr = bytesAddressPair[1]
msgFrom = 'Message from Client:{}'.format(clientBuf.decode('utf-8'))
print(msgFrom)
for workerAddressPort in workerAddressPorts:
UDPServerSocket.sendto(clientBuf, workerAddressPort) # send file name to worker
print(f'Clients request has been sent to Worker {workerAddressPort[0]}')
workerBuf = UDPServerSocket.recvfrom(bufSize)[0] # saving data from worker
print(f'Request recieved.')
UDPServerSocket.sendto(workerBuf, clientAddr) # sending data to client
print('Packet from Worker has been sent to Client')
while not workerBuf: # split file to prevent buffer overflow
workerBuf = UDPServerSocket.recvfrom(bufSize)[0]
print(f'Packet received.')
UDPServerSocket.sendto(workerBuf, clientAddr)
print('Packet from worker has been sent to Client')
print('File has been sent to Client.')
Client:
import sys
msgFrom = input('Name of file: ')
print(msgFrom)
bytesToSend = str.encode(msgFrom, 'utf-8')
serverAddressPort = ("127.0.0.1", 50001)
bufSize = 1024
# create UDP Client Socket and send to server
UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPClientSocket.sendto(bytesToSend, serverAddressPort)
while (True):
try:
serverBuf = UDPClientSocket.recvfrom(bufSize)[0]
if len(serverBuf) > 0:
print('Packet incoming...')
msg = serverBuf.decode('utf-8')
if msg == 'NO_FILE':
print('No such file exists.')
break
elif msg == 'END_OF_FILE':
print('Empty file.')
break
else:
f = open(msgFrom, 'wb')
f.write(serverBuf)
f.close()
except Exception as e:
print(e)
Worker:
import socket
import time
from os.path import exists
bufSize = 1024
msg = "Worker is connecting..."
print(msg)
serverAddressPort = ("127.0.0.1", 50001)
# Create a datagram socket and bind to address and ip
UDPWorkerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
UDPWorkerSocket.bind(('127.0.0.1', 50002))
print("Worker is connected and waiting...")
while True:
time.sleep(1)
bytesAddressPair = UDPWorkerSocket.recvfrom(bufSize)
msg = bytesAddressPair[0]
addr = bytesAddressPair[1]
print('Packet Incoming...')
file_name = msg.decode('utf-8')
script_dir = os.path.dirname("C:/Users/Vic/Documents/3rd Year TCD/CSU33031 Computer Networks/Assignments/Assignment1.3/Files to send")
abs_file_path = os.path.join(script_dir, file_name)
if exists(file_name):
f = open(file_name, 'rb')
data = f.read(bufSize)
while data:
if UDPWorkerSocket.sendto(data, serverAddressPort):
data = f.read(bufSize)
time.sleep(1)
print('Sent to Server.')
else:
UDPWorkerSocket.sendto(str.encode('NO_FILE'), serverAddressPort)
print(f'{file_name} was not found. Moving to next available worker..')
Hoping that the for statement in the server, iterates the two worker files(only included one) so if it can't find the file in one worker it moves to the other
*the client is connected to a different network as the two workers. The server is connected to both networks
Thanks in advance!!

create loop to switch from one socket to another

So I have successfully created a socket connection to one client and another, but I am having trouble getting them to switch from one another with loops, did some while true and if statements to make the program recognize when one system wants to switch based on user input but I don't think I'm doing it right. Can some one help me out with a code to switch back and forth
The following is the code I'm attempting to implement.
This is the code on my computer:
import socket,sys,os,time
T2='yourturn'
serverAddr = ('192.168.0.120', 20104)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#client.connect(serverAddr)
sock = client
client.connect(('192.168.0.120', 20104))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def redirectOut(port=20104, host='192.168.0.11'):
"""
connect caller's standard output stream to a socket for GUI to listen
start caller after listener started, else connect fails before accept
"""
sock = client
# caller operates in client mode
file = sock.makefile('w') # file interface: text, buffered
sys.stdout = file
# make prints go to sock.send
return sock
########################################33333
time.sleep(10)
HOST = ''
PORT2 = 20105
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
try:
l=s.bind((HOST, PORT2))
except socket.error as msg:
print('Bind failed. ')
sys.exit()
print('Socket bind complete')
s.listen(10)
print('Socket now listening')
conn, addr = s.accept()
print('Connected to ' + addr[0] + ':' + str(addr[1]))
####################################################
time.sleep(10)
while True:
if T2!='yourturn':
data = conn.recv(1024)
line = data.decode # convert to string (Python 3 only)
T2=print(line)
else :
if T2=='myturn':
break
else:
redirectOut()
T2=print(input())
this is the code on my begalbone black:
import socket
import sys
import os, time
HOST = ''
PORT2 = 20104
T='yourturn'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
try:
l=s.bind((HOST, PORT2))
except socket.error as msg:
print('Bind failed. ')
sys.exit()
print('Socket bind complete')
s.listen(10)
print('Socket now listening')
conn, addr = s.accept()
print('Connected to ' + addr[0] + ':' + str(addr[1]))
#################################################################
time.sleep(15)
serverAddr = ('192.168.0.11', 20105)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock = client
try:
sock.connect(('192.168.0.11', 20105))
fsr = 'P9_40'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except TimeoutError:
os.system('reboot')
def redirectOut(port=20105, host='192.168.0.120'):
"""
connect caller's standard output stream to a socket for GUI to listen
start caller after listener started, else connect fails before accept
"""
sock = client
# caller operates in client mode
file = sock.makefile('w') # file interface: text, buffered
sys.stdout = file # make prints go to sock.send
return sock
##############################################################
time.sleep(10)
while True:
if T!='myturn':
data = conn.recv(1024)
line = data.decode('UTF-8') # convert to string (Python 3 only)
T=print(line)
else:
redirectOut()
if T=='yourturn':
break
else:
T=print(input())
So tried this while loop: but its still hanging up, I think I'm close:
T2='yourturn'
while True:
#for line in 'Python':
print(T2)
time.sleep(10)
if T2=='myturn':
data = conn.recv(1024)
line = data.decode
print("myturn print")
l=print(line)
if l=="yourturn":
continue
if T2=="yourturn" or T2!='myturn':
print(T2)
print('myturn send')
redirectOut()# convert to string (Python 3 only)
k=input()
if k=="myturn":
T2='myturn'
continue
Tried the folowing but reciving machine is hanging up when myturn is input:
sending:
time.sleep(3)
T2='yourturn'
print('here')
while True:
#for line in 'Python':
#print(T2)
#time.sleep(10)
if T2=='myturn':
data = conn.recv(1024)
line = data.decode('UTF-8')
#print("myturn print")
l=print(line)
if l=="yourturn":
T2='yourturn'
continue
if T2=="yourturn" and T2!='myturn':
#print(T2)
#print('myturn send')
redirectOut()# convert to string (Python 3 only)
k=input()
print(k)
if k=="myturn":
T2=print('myturn')
T2='myturn'
print('there')
continue
receiving:
time.sleep(3)
T='yourturn'
while True:
#for line in 'Python':
#print(T)
if T=='yourturn':
data = conn.recv(1024)
line = data.decode('UTF-8')
#print("myturn print")
l=print(line)
if l=='myturn':
T='myturn'
continue
if l=='exit':
client.close()
break
if T=='myturn' and T!='yourturn':
#print('myturn send')
redirectOut()# convert to string (Python 3 only)
k=input()
print(k)
if k=='yourturn':
T=print('yourturn')
continue
EDIT SOLUTION:
I finally figured it out, removed my reditectOut function and opened the port with windows firewall to implement this code
my computer:
T2='yourturn'
while True:
if T2=='myturn':
data = conn.recv(1024)
line = data.decode('UTF-8')
print(line)
l=line
if l=="yourturn":
T2='yourturn'
continue
if T2=="yourturn" and T2!='myturn':
k=input()
client.sendto(k.encode('utf-8'),('192.168.0.120', 20104))
if k=="myturn":
T2='myturn'
continue
Beagle bone black:
time.sleep(3)
T='yourturn'
while True:
if T=='yourturn':
data = conn.recv(1024)
line = data.decode('UTF-8')
print(line)
l=line
if l=='myturn':
T='myturn'
continue
if T=='myturn' and T!='yourturn':
k=input()
client.sendto(k.encode('utf-8'),('192.168.0.11', 20105))
if k=='yourturn':
T='yourturn'
continue

Send big file over socket

I have a video file and want to send it over socket. Video is send to the client but video is not playable and also video size received is 2 KB. And acutely video size is 43 MB. What is the problem?
Server:
import socket
try:
soc = socket.socket()
print('socked created.')
host = ''
port = 8080
soc.bind((host, port))
print('soc bound.')
soc.listen(10)
print('waiting for connecting...')
con, addr = soc.accept()
print('server connected to IP: ' + addr[0] + " port: " + str(addr[1]))
while True:
filename = input('enter filename: ')
file = open(filename, 'rb')
sendfile = file.read(9000000)
con.send(sendfile)
print("file has been send.")
break
con.close()
soc.close()
except socket.error as err:
print('error ', str(err))
client:
import socket
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('socked created. waiting for connecting to server...')
server_address = ("192.168.1.3", 8080)
soc.connect(server_address)
print('connected to the server.')
while True:
recvfile = soc.recv(9000000)
savefilebyname = input("enter file name: ")
openfile = open(savefilebyname, 'wb')
openfile.write(recvfile)
openfile.close()
break
print("File has been received.")
soc.close()
Check the return value of send and recv. The 9000000 value is a maximum but not guaranteed value to send/recv. Alternatively, use sendall.
For recv, you have to loop until you receive all the data. If you close the socket after the file is sent, recv will return zero when all the data is received.
FYI, your while True: in both files never loops due to the break, so they are unnecessary.
Here's something that should work...
server.py
import socket
soc = socket.socket()
soc.bind(('',8080))
soc.listen(1)
print('waiting for connection...')
with soc:
con,addr = soc.accept()
print('server connected to',addr)
with con:
filename = input('enter filename to send: ')
with open(filename, 'rb') as file:
sendfile = file.read()
con.sendall(sendfile)
print('file sent')
client.py
import socket
soc = socket.socket()
soc.connect(('localhost',8080))
savefilename = input("enter file name to receive: ")
with soc,open(savefilename,'wb') as file:
while True:
recvfile = soc.recv(4096)
if not recvfile: break
file.write(recvfile)
print("File has been received.")

Transferring multiple files from one host to another

I'm new to python socket programming. I want to transfer 5 files (photos) from one host in mininet to another. The name of these files are numbered respectively (I mean 1.jpg, 2.jpg and ...). The problem is that when I run these codes, the first photo is transferred correctly but others become corrupted. What's the problem:
sender.py
import socket
import sys
buf = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('10.0.0.1',12345))
for i in range(1,6):
with open("%d.jpg" % (i),'rb') as f:
data = f.read(buf)
while 1:
if not data:
break
s.sendall(data)
data = f.read(buf)
s.close()
receiver.py:
import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('10.0.0.1', 12345))
buf = 1024
s.listen(1)
conn , addr = s.accept()
for i in range(6,11):
with open("%d.jpg" % (i),'wb') as f:
while 1:
data = conn.recv(buf)
#print(data[:10])
#print "PACKAGE RECEIVED..."
f.write(data)
if not data: break
#conn.close()
#s.close()
The simple solution to your problem is to create a new connection for each file. The code below does that.
Sender
from __future__ import print_function
import socket
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def send_file(fname):
with open(fname, 'rb') as f:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except socket.error as err:
print(err, HOST, PORT)
sock.close()
return
while True:
data = f.read(BUFSIZE)
if not data:
break
while data:
sent = sock.send(data)
data = data[sent:]
sock.close()
fnames = [
'test0.jpg',
'test1.jpg',
'test2.jpg',
'test3.jpg',
]
def main():
for fname in fnames:
send_file(fname)
if __name__ == '__main__':
main()
Receiver
from __future__ import print_function
import socket
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.bind((HOST, PORT))
except socket.error as err:
print('Bind failed', err)
return
sock.listen(1)
print('Socket now listening at', HOST, PORT)
file_number = 0
try:
while True:
conn, addr = sock.accept()
print('Connected with', *addr)
fname = 'image%d.jpg' % file_number
with open(fname, 'wb') as f:
while True:
data = conn.recv(BUFSIZE)
if not data:
break
f.write(data)
conn.close()
print(fname, 'saved\n')
file_number += 1
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
sock.close()
if __name__ == '__main__':
main()
You need to hit CtrlC or Break (depending on your OS) to exit the receiver.
But using those numeric file names at the receiver isn't very satisfactory , so I decided to make it a little more complicated. :) In the following version we send the file name before the file data. That's slightly tricky because the receiver needs to separate the file name from the actual file data. If each socket.recv call corresponded to a socket.send call that would be easy, but that's not guaranteed to happen: the received bytes may be split differently from how they were sent. The receiver needs to buffer the bytes so it can break them up correctly. See the Socket Programming HOWTO for details.
So that the receiver knows where the file name ends we first send a single byte that encodes the length of the file name. A byte can hold a number from 0 to 255, so this code can't handle file names longer than that. After the length byte, we send the file name itself, encoded using UTF-8. And then we send the actual file contents.
The receiver uses a class named Receiver to handle the buffering. This class has a .get method which we can use to get a specified number of bytes. We use that method to get the file name length and the file name. And then we use Receiver's .save method to save the received file contents to a new file.
This code is a little bit messy because it's designed to run on Python 2 and Python 3, in any combination. It'd be somewhat neater if it was for Python 3 only. I hard-coded 'localhost' as the host name, since I only have one computer, so I couldn't test it over a network, but I'm confident that it will work correctly on a network.
Here's the sender:
from __future__ import print_function
import socket
from struct import pack
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
def send(sock, data):
while data:
sent = sock.send(data)
data = data[sent:]
def send_file(fname):
with open(fname, 'rb') as f:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except socket.error as err:
print(err, HOST, PORT)
sock.close()
return
# Send the file name length & the filename itself in one packet
send(sock, pack('B', len(fname)) + fname.encode())
while True:
data = f.read(BUFSIZE)
if not data:
break
send(sock, data)
sock.close()
fnames = [
'test1.gif',
'test2.jpg',
'test3.png',
'test4.pdf',
]
def main():
for fname in fnames:
send_file(fname)
if __name__ == '__main__':
main()
And here's the receiver:
from __future__ import print_function
import socket
from struct import unpack
HOST = 'localhost'
PORT = 12345
BUFSIZE = 4096
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.bind((HOST, PORT))
except socket.error as err:
print('Bind failed', err)
return
sock.listen(1)
print('Socket now listening at', HOST, PORT)
try:
while True:
conn, addr = sock.accept()
print('Connected with', *addr)
# Create a buffer for this connection
receiver = Receiver(conn)
# Get the length of the file name
name_size = unpack('B', receiver.get(1))[0]
# Get the file name itself
name = receiver.get(name_size).decode()
print('name', name)
# Save the file
receiver.save(name)
conn.close()
print('saved\n')
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
sock.close()
if __name__ == '__main__':
main()
You should use it like:
with open("%d.jpg" % (i),'wb') as f:
while 1:
data = conn.recv(buf)
#print(data[:10])
#print "PACKAGE RECEIVED..."
f.write(data)
if not data: break
this way f gets closed automatically when you leave the with block when you exit the while.
I guess you need to extend the protocol so that the receiver knows what it gets and that you can let it act on that. Something like a 'begin-of-transfer' ... sending the filename, sending the data, sending 'end-of-transfer' that makes the receiver close the file

print contents of file - python socket

I'm trying to print the contents of a file to the client using the defined command 'get'. I am not getting the contents of the file instead the contents are getting over written with Server Says... get test.txt.
Here is my client code:
import socket
import sys
import os
HOST = 'localhost'
PORT = 8082
size = 1024
def ls():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.send(userInput)
result = s.recv(size)
print result
s.close()
return
def put(commandName):
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open(inputFile, 'rb') as file_to_send:
for data in file_to_send:
socket1.sendall(data)
print 'PUT Successful'
socket1.close()
return
def get(commandName):
socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket1.connect((HOST, PORT))
socket1.send(commandName)
string = commandName.split(' ', 1)
inputFile = string[1]
with open(inputFile, 'wb') as file_to_write:
while True:
data = socket1.recv(1024)
print data
if not data:
break
print data
file_to_write.write(data)
file_to_write.close()
print 'GET Successful'
#socket1.close()
return
done = False
while not done:
userInput = raw_input()
if "quit" == userInput:
done = True
elif "ls" == userInput:
ls()
else:
string = userInput.split(' ', 1)
if (string[0] == 'put'):
put(userInput)
elif (string[0] == 'get'):
get(userInput)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.send(userInput)
data = s.recv(size)
s.close()
print 'Received:', data
And server code:
import socket
import os
import sys
host = ''
port = 8082
backlog = 5
size = 1024
serverID = socket.gethostbyname(socket.gethostname())
info = 'SERVER ID: {} port: {}'.format(serverID, port)
print info
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
done = False
# Loop until client sends 'quit' to server
while not done:
client, address = s.accept()
data = client.recv(size)
print "Server received: ", data
if data:
client.send("Server Says... " + data)
if data == "quit":
done = True
elif data == "ls":
data = os.listdir("C://")
client.send(data[0])
else:
string = data.split(' ', 1)
dataFile = string[1]
if (string[0] == 'put'):
with open(dataFile, 'wb') as file_to_write:
while True:
data = client.recv(1024)
if not data:
break
file_to_write.write(data)
file_to_write.close()
break
print 'Receive Successful'
elif (string[0] == 'get'):
with open(dataFile, 'rb') as file_to_send:
for data in file_to_send:
client.send(data)
print 'Send Successful'
client.close()
s.close()
print "Server exiting."
You are getting the content of the file but it is empty... and your code works just because you probably run it in the same directory.
Your client open file to write (and then it is empty) and the server reads it (both code use the same file name). You probably wanted to read file from C:\ so you should change server code and replace line:
with open(dataFile, 'rb') as file_to_send:
with:
with open('C:\\' + dataFile, 'rb') as file_to_send:
No matter what you send to the server this condition is true so you get "server says..."
if data:
client.send("Server Says... " + data)
You have also several flaws in you client I think. Like your commands are sent 2 times: once in the client 'main' when you do:
s.send(userInput)
And once in the functions like get and ls :
socket1.send(commandName)

Categories

Resources