Transferring multiple files from one host to another - python

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

Related

How to send zip file using Python sockets?

This is my server:
//server.py
import sys
import socket
HOST = sys.argv[1] if len(sys.argv) > 1 else '0.0.0.0'
PORT = int(sys.argv[2] if len(sys.argv) > 2 else 5555)
SIZE = 1024
FORMAT = "utf-8"
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
client = s.accept()
while True:
print(f"\033[33m[*] Listening as {HOST}:{PORT}\033[m")
print(f"\033[32m[!] Client connected {client[1]}\033[m")
client[0].send('copy trash'.encode())
filename = client[0].recv(SIZE).decode(FORMAT)
print(f"[RECV] Receiving the filename.")
file = open(filename, "w")
client[0].send("Filename received.".encode(FORMAT))
data = client[0].recv(SIZE).decode(FORMAT)
print(f"[RECV] Receiving the file data.")
file.write(data)
client[0].send("File data received".encode(FORMAT))
s.close()
This is my client:
//client.py
import sys
import socket
import subprocess
import tqdm
import shutil
HOST = sys.argv[1] if len(sys.argv) > 1 else '0.0.0.0'
PORT = int(sys.argv[2] if len(sys.argv) > 2 else 5555)
FORMAT = "utf-8"
SIZE = 1024
s = socket.socket()
s.connect((HOST, PORT))
msg = s.recv(1024).decode()
print('[*] server:', msg)
if(msg.lower() == "copy trash"):
shutil.make_archive("/root/trashcopy", 'zip', "/root/.local/share/Trash")
file = open("/root/trashcopy.zip", "r")
data = file.read()
s.send("trashcopy.zip".encode(FORMAT))
msg = s.recv(SIZE).decode(FORMAT)
print(f"[SERVER]: {msg}")
s.send(data.encode(FORMAT))
msg = s.recv(SIZE).decode(FORMAT)
print(f"[SERVER]: {msg}")
What am I trying to do?
I'm trying to make a zip file with files from the recycle bin and send it to the server, however, there's a problem with encoding and an error is thrown at this line:
s.send(data.encode(FORMAT))
This is the error:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x95 in position 124: invalid start byte
How can I fix this? When it's a .txt file, for example, I can send the file without problems.
It's a decoding problem, I've tried to decode in other formats besides utf-8 but it didn't work.
There were several issues with your code. For example, when reading the zip (binary) file, you should read it as bytes, not as string, and send it as bytes. Also, your server needs to know in advance the expected file size to be able to read the file in chunks. You can do that using byte ordering. Below is a working example. Credits go to this for the data receiving approach, which was slightly modified to read the data in chunks, as your code requires.
EDIT: The server has been modified to support reconnection from the client. Thus, client = s.accept() has been moved to inside the while loop and client's connection gets closed after the file has been received.
server.py
import sys
import socket
HOST = sys.argv[1] if len(sys.argv) > 1 else '0.0.0.0'
PORT = int(sys.argv[2] if len(sys.argv) > 2 else 5555)
SIZE = 1024
BYTEORDER_LENGTH = 8
FORMAT = "utf-8"
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
while True:
client = s.accept()
print(f"\033[33m[*] Listening as {HOST}:{PORT}\033[m")
print(f"\033[32m[!] Client connected {client[1]}\033[m")
print(f"Sending 'copy trash' msg")
client[0].send('copy trash'.encode())
print(f"[RECV] Receiving the file size")
file_size_in_bytes = client[0].recv(BYTEORDER_LENGTH)
file_size= int.from_bytes(file_size_in_bytes, 'big')
print("File size received:", file_size, " bytes")
client[0].send("File size received.".encode(FORMAT))
print(f"[RECV] Receiving the filename.")
filename = client[0].recv(SIZE).decode(FORMAT)
print(f"[RECV]Filename received:", filename)
client[0].send("Filename received.".encode(FORMAT))
print(f"[RECV] Receiving the file data.")
# Until we've received the expected amount of data, keep receiving
packet = b"" # Use bytes, not str, to accumulate
while len(packet) < file_size:
if(file_size - len(packet)) > SIZE: # if remaining bytes are more than the defined chunk size
buffer = client[0].recv(SIZE) # read SIZE bytes
else:
buffer = client[0].recv(file_size - len(packet)) # read remaining number of bytes
if not buffer:
raise Exception("Incomplete file received")
packet += buffer
with open(filename, 'wb') as f:
f.write(packet)
print(f"[RECV] File data received.")
client[0].send("File data received".encode(FORMAT))
client[0].close()
s.close()
client.py
import sys
import socket
import subprocess
import shutil
import os
HOST = sys.argv[1] if len(sys.argv) > 1 else '127.0.0.1'
PORT = int(sys.argv[2] if len(sys.argv) > 2 else 5555)
FORMAT = "utf-8"
SIZE = 1024
BYTEORDER_LENGTH = 8
s = socket.socket()
s.connect((HOST, PORT))
msg = s.recv(SIZE).decode()
print('[*] server:', msg)
if(msg.lower() == "copy trash"):
#shutil.make_archive("/root/trashcopy", 'zip', "/root/.local/share/Trash")
shutil.make_archive("_trashcopy", 'zip', "Trash")
file_size = os.path.getsize('_trashcopy.zip')
print("File Size is :", file_size, "bytes")
file_size_in_bytes = file_size.to_bytes(BYTEORDER_LENGTH, 'big')
print("Sending the file size")
s.send(file_size_in_bytes)
msg = s.recv(SIZE).decode(FORMAT)
print(f"[SERVER]: {msg}")
print("Sending the file name")
s.send("trashcopy.zip".encode(FORMAT))
msg = s.recv(SIZE).decode(FORMAT)
print(f"[SERVER]: {msg}")
print("Sending the file data")
with open ('_trashcopy.zip','rb') as f1:
s.send(f1.read())
msg = s.recv(SIZE).decode(FORMAT)
print(f"[SERVER]: {msg}")
s.close()

multithreading sockets in python

I'm trying to build up a non-blocking UDP-Server that listens to different ports and receives data-packages until timeout. Unfortunatly, I cannot change the client-side and UDP is mandatory.
Receiving files works fine. The issue is, that creating the workers is a blocking operation. I'd like to have it non-blocking so all workers are called in parallel. Also each worker should run in a loop like while True but that was blocking, too.
Here is my code:
#!/usr/bin/env python
from socket import *
import sys
import select
import threading
threads = []
def worker(port):
host="192.168.88.51"
s = socket(AF_INET,SOCK_DGRAM)
s.bind((host,port))
addr = (host,port)
buf=128
data,addr = s.recvfrom(buf)
filename = str(port)+".data"
print str(port)+" received File:"
f = open(filename,'wb')
data, addr = s.recvfrom(buf)
try:
while(data):
f.write(data)
s.settimeout(1)
data,addr = s.recvfrom(buf)
except timeout:
f.close()
s.close()
print "File Downloaded"
for i in range(1300,1305):
wrk = worker(i)
threads.append(wrk)
This will work as you intended except that it will overwrite the file a new each time new data is sent without timing out.
Timeout represents end of whole connection. But you can easily rework this to add data to same file or create a new file or do whatever you need.
#! /usr/bin/env python
from socket import AF_INET, SOCK_DGRAM
import socket
import threading
class Server (threading.Thread):
def __init__ (self, host="192.168.88.51", port=123, bufsize=128):
threading.Thread.__init__(self)
self.host = host
self.port = port
self.bufsize = bufsize
self.done = threading.Event()
def opensock (self):
s = socket.socket(AF_INET, SOCK_DGRAM)
s.bind((self.host, self.port))
s.settimeout(0.001)
return s
def run (self):
host = self.host
port = self.port
self.s = s = self.opensock()
print "Waiting for connection on", host+":"+str(port)
while not self.done.isSet():
try:
data, addr = s.recvfrom(self.bufsize)
print "Connection from", addr
s.settimeout(1)
self.recvdata(data, s, addr)
s.settimeout(0.001)
except socket.timeout: pass
except:
raise
self.done.set()
s.close()
print "Server on '%s:%s' stopped!" % (host, port)
def recvdata (self, initdata, conn, addr):
bufsize = self.bufsize
filename = str(self.port)+".data"
print "Opening file", filename
f = open(filename, "wb")
print "Receiving & writingrest of data from", addr
data = initdata
while data and not self.done.isSet():
f.write(data)
try:
data, addr = conn.recvfrom(bufsize)
except socket.timeout: break
f.close()
if self.done.isSet():
print "Forcefully interrupted transmission"
else:
print "File Downloaded"
def stop (self):
self.done.set()
self.s.close()
servers = []
for port in xrange(123, 150):
try:
s = Server(port=port)
s.start()
servers.append(s)
except Exception as e:
print e
raw_input("Press enter to send data to one of ports for testing . . . ")
import random
a = servers[0].host
p = random.choice(servers).port
print "data will be sent to port '%s:%i'" % (a, p)
k = socket.socket(AF_INET, SOCK_DGRAM)
k.connect((a, p))
k.send("1234567890")
k.send("asdfghjkl")
k.send("0987654321")
k.close()
raw_input("Press enter to close the program . . . ")
# Stop all servers:
for s in servers:
s.stop()
# Make sure all of them terminated:
for s in servers:
s.join()
That did it. Figured it out myself.
#!/usr/bin/env python
from socket import *
import sys
import select
import multiprocessing
def worker(port):
print "started: "+str(port)
host="192.168.88.51"
s = socket(AF_INET,SOCK_DGRAM)
s.bind((host,port))
addr = (host,port)
buf=128
data,addr = s.recvfrom(buf)
filename = str(port)+".jpg"
print str(port)+" received File:"
f = open(filename,'wb')
data, addr = s.recvfrom(buf)
try:
while(data):
f.write(data)
s.settimeout(1)
data,addr = s.recvfrom(buf)
except timeout:
f.close()
s.close()
print "File Downloaded"
for i in range(1300,1305):
multiprocessing.Process(target=worker, args=(i,)).start()

What is the proper way of sending a large amount of data over sockets in Python?

Recently I wrote some code (client and server) to send an image - the client simply uploads the image to the server, just using the socket module: Sending image over sockets (ONLY) in Python, image can not be open.
However, the image sending part is now what I am concerned with. This is the original image I'm using:
In my server code (which receives the images), I have these lines:
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
data = sock.recv(40960000)
if not data:
myfile.close()
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
But I don't think this is the best way of doing it. I think I should instead implement the server such that it receives the data in chunks:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 2905
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if data:
if data.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size %s' % size
sock.sendall("GOT SIZE")
elif data.startswith('BYE'):
sock.shutdown()
else :
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
amount_received = 0
while amount_received < size:
data = sock.recv(4096)
amount_received += len(data)
print amount_received
if not data:
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()
But when I do this, the server prints:
got size 54674
4096
8192
12288
16384
20480
24576
28672
32768
36864
40960
45056
49152
50578
And then seems to hang, and the client hangs too. However, at the server's side I can see only a piece of the image the client wanted to send:
It seems like there are some bytes missing. What is the proper way of sending a huge amount of data (images, other type of file) using ONLY sockets?
I'm assuming that you have a particular reason for doing this with naked sockets, such as self-edification, which means that I won't answer by saying "You accidentally forgot to just use HTTP and Twisted", which perhaps you've heard before :-P. But really you should look at higher-level libraries at some point as they're a lot easier!
Define a protocol
If all you want is to send an image, then it can be simple:
Client -> server: 8 bytes: big endian, length of image.
Client -> server: length bytes: all image data.
(Client <- server: 1 byte, value 0: indicate transmission received - optional step you may not care if you're using TCP and just assume that it's reliable.)
Code it
server.py
import os
from socket import *
from struct import unpack
class ServerProtocol:
def __init__(self):
self.socket = None
self.output_dir = '.'
self.file_num = 1
def listen(self, server_ip, server_port):
self.socket = socket(AF_INET, SOCK_STREAM)
self.socket.bind((server_ip, server_port))
self.socket.listen(1)
def handle_images(self):
try:
while True:
(connection, addr) = self.socket.accept()
try:
bs = connection.recv(8)
(length,) = unpack('>Q', bs)
data = b''
while len(data) < length:
# doing it in batches is generally better than trying
# to do it all in one go, so I believe.
to_read = length - len(data)
data += connection.recv(
4096 if to_read > 4096 else to_read)
# send our 0 ack
assert len(b'\00') == 1
connection.sendall(b'\00')
finally:
connection.shutdown(SHUT_WR)
connection.close()
with open(os.path.join(
self.output_dir, '%06d.jpg' % self.file_num), 'w'
) as fp:
fp.write(data)
self.file_num += 1
finally:
self.close()
def close(self):
self.socket.close()
self.socket = None
# could handle a bad ack here, but we'll assume it's fine.
if __name__ == '__main__':
sp = ServerProtocol()
sp.listen('127.0.0.1', 55555)
sp.handle_images()
client.py
from socket import *
from struct import pack
class ClientProtocol:
def __init__(self):
self.socket = None
def connect(self, server_ip, server_port):
self.socket = socket(AF_INET, SOCK_STREAM)
self.socket.connect((server_ip, server_port))
def close(self):
self.socket.shutdown(SHUT_WR)
self.socket.close()
self.socket = None
def send_image(self, image_data):
# use struct to make sure we have a consistent endianness on the length
length = pack('>Q', len(image_data))
# sendall to make sure it blocks if there's back-pressure on the socket
self.socket.sendall(length)
self.socket.sendall(image_data)
ack = self.socket.recv(1)
# could handle a bad ack here, but we'll assume it's fine.
if __name__ == '__main__':
cp = ClientProtocol()
image_data = None
with open('IMG_0077.jpg', 'r') as fp:
image_data = fp.read()
assert(len(image_data))
cp.connect('127.0.0.1', 55555)
cp.send_image(image_data)
cp.close()
A simple way is to send data size as the first 4 bytes of your data and then read complete data in one shot. Use the below functions on both client and server-side to send and receive data.
def send_data(conn, data):
serialized_data = pickle.dumps(data)
conn.sendall(struct.pack('>I', len(serialized_data)))
conn.sendall(serialized_data)
def receive_data(conn):
data_size = struct.unpack('>I', conn.recv(4))[0]
received_payload = b""
reamining_payload_size = data_size
while reamining_payload_size != 0:
received_payload += conn.recv(reamining_payload_size)
reamining_payload_size = data_size - len(received_payload)
data = pickle.loads(received_payload)
return data
you could find sample program at https://github.com/vijendra1125/Python-Socket-Programming.git
The problem is you are not incrementing amount_received for the first chunk of the data received.
Fix below:
#!/usr/bin/env python
import random
import socket, select
from time import gmtime, strftime
from random import randint
imgcounter = 1
basename = "image%s.png"
HOST = '127.0.0.1'
PORT = 2905
connected_clients_sockets = []
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(10)
connected_clients_sockets.append(server_socket)
while True:
read_sockets, write_sockets, error_sockets = select.select(connected_clients_sockets, [], [])
for sock in read_sockets:
if sock == server_socket:
sockfd, client_address = server_socket.accept()
connected_clients_sockets.append(sockfd)
else:
try:
data = sock.recv(4096)
txt = str(data)
if data:
if data.startswith('SIZE'):
tmp = txt.split()
size = int(tmp[1])
print 'got size %s' % size
sock.sendall("GOT SIZE")
elif data.startswith('BYE'):
sock.shutdown()
else :
myfile = open(basename % imgcounter, 'wb')
myfile.write(data)
amount_received = len(data) # The fix!
while amount_received < size:
data = sock.recv(4096)
amount_received += len(data)
print amount_received
if not data:
break
myfile.write(data)
myfile.close()
sock.sendall("GOT IMAGE")
sock.shutdown()
except:
sock.close()
connected_clients_sockets.remove(sock)
continue
imgcounter += 1
server_socket.close()

python 3.4.3 file is not writing completly

The following is complete client , server and sendproc codes:
Client.py
from socket import *
import pickle
import sendproc
import struct
s = socket(AF_INET, SOCK_STREAM) # Create a socket object
host = "192.168.1.4" # Get local machine name
port = 1094 # Reserve a port for your service.
s.connect((host, port))
with open("file.txt",'rb') as f:
print ('file opened')
print('Sending file...')
for data in f:
print(data)
print("MSG sent")
sendproc.send_msg(s, data)
Server.py
from socket import *
import pickle
import sendproc
port = 1094 # Reserve port for service.
s = socket(AF_INET,SOCK_STREAM) # Create a socket object
host = "192.168.1.4" # Get local machine name
s.bind((host, port)) # Bind to the port
s.listen(5)
print('server is listening')
conn,addr = s.accept()
with open("file1.txt",'w') as fb:
print("File downloading\n",fb)
while True:
print("hi")
data = sendproc.recv_msg(conn)
print(data)
if not data:
print("No data")
break
fb.write(data)
fb.flush()
print("Download complete\n")
SendRecieveProcedure.py
import struct
def send_msg(s, msg):
msg2 = struct.pack('>I', len(msg)) + msg
s.send(msg2)
def recv_msg(s):
# Read message length and unpack it into an integer
raw_msglen = s.recv(4)
print(raw_msglen)
if not raw_msglen:
return None
n = struct.unpack('>I',raw_msglen)[0]
# Read the message data
data = ' '
while len(data) < n:
packet = s.recv(n - len(data)).decode("cp437")
if not packet:
return None
data += packet
#print("hwllo",data )
return data
output prints correctly to the console, but if I go open up the file it's only writing starting lines.so what is the problem in code

Why does the file not transfer completely? Python Socket Programming

The problem I'm having is to get a file from the server. Lets say I want to
"get ./testing.pdf" which sends the pdf from the server to the client. It sends but it is always missing bytes. Is there any problems with how I am sending the data. If so how can I fix it? I left out the code for my other functionalities since they are not used for this function.
server.py
import socket, os, subprocess # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
#host = ''
port = 5000 # Reserve a port for your service.
bufsize = 4096
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
while True:
userInput = c.recv(1024)
.... CODE ABOUT OTHER FUNCTIONALITY
elif userInput.split(" ")[0] == "get":
print "inputed get"
somefile = userInput.split(" ")[1]
size = os.stat(somefile).st_size
print size
c.send(str(size))
bytes = open(somefile).read()
c.send(bytes)
print c.recv(1024)
c.close()
client.py
import socket, os # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
#host = '192.168.0.18'
port = 5000 # Reserve a port for your service.
bufsize = 1
s.connect((host, port))
print s.recv(1024)
print "Welcome to the server :)"
while 1 < 2:
userInput = raw_input()
.... CODE ABOUT OTHER FUNCTIONALITY
elif userInput.split(" ")[0] == "get":
print "inputed get"
s.send(userInput)
fName = os.path.basename(userInput.split(" ")[1])
myfile = open(fName, 'w')
size = s.recv(1024)
size = int(size)
data = ""
while True:
data += s.recv(bufsize)
size -= bufsize
if size < 0: break
print 'writing file .... %d' % size
myfile = open('Testing.pdf', 'w')
myfile.write(data)
myfile.close()
s.send('success')
s.close

Categories

Resources