I'm new with python, I am trying the following, I have two calsess: Server.py and Client.py I want to send all the files that exists in server directory to some directory at the client side. i.e
C:\ServerDir\file1.txt
C:\ServerDir\file2.txt
C:\ServerDir\file3.txt...
would go to:
D:\ClientDir\file1.txt
D:\ClientDir\file2.txt
D:\ClientDir\file3.txt...
For now I can send single file, Server.py:
import socket # Import socket module
port = 60000 # Reserve a port for your service.
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
print ('Server listening....')
while True:
conn, addr = s.accept() # Establish connection with client.
print ('Got connection from', addr)
data = conn.recv(1024)
print('Server received', repr(data))
filename='C:\\Users\\Desktop\\File.txt'
f = open(filename,'rb')
l = f.read(1024)
while (l):
conn.send(l)
print('Sent ',repr(l))
l = f.read(1024)
f.close()
print('Done sending')
conn.send('Thank you for connecting'.encode())
conn.close()
Client.py:
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 60000 # Reserve a port for your service.
s.connect((host, port))
s.send("Hello server!".encode())
with open('C:\\Users\\Desktop\\Python\\gg.txt', 'wb') as f:
print ('file opened')
while True:
print('receiving data...')
data = s.recv(1024)
print('data=%s', (data))
if not data:
break
# write data to a file
f.write(data)
f.close()
print('Successfully get the file')
s.close()
print('connection closed')
I have tried to loop over all files in server side like:
for file in os.listdir('C:\\Users\\Desktop\\'):
filename = 'C:\\Users\\Desktop\\'+file
but it sends only the first file.
The critical bit is - how do you know a file ended? In your current implementation, if the connection ends, so does the file (and then you have a closed socket, so no chance for a next file).
There are two solutions:
Simple: Make the client open a new connection for each file (i.e. move stuff into the loop); if you get an instant broken connection, maybe that's the end of everything
Better: Have the server send the file size before the file itself. Have the client only write data to a file till the size is correct, then start working on a new file.
Of course, you still have an issue about how the server will know what file names to assign the incoming files. You could put those into the "header" that by now likely consists of filename :)
If you're wondering, this is exactly (well, close enough) what HTTP does. Each file has headers, then an empty line, then a stream of bytes whose length was communicated before by the Content-Length header. After that, the connection can be reused for the next file. If Content-Length is missing, the agent will read till the connection is broken (and the next file will need to establish a new connection).
Related
I want to send i file over TCP but when i try to run this the connection fails, the server receives the file but it gives this error: ERROR: Client timed out before sending a file
import selectors
import sys
from socket import *
import sock
sel1 = selectors.DefaultSelector()
print(len(sys.argv), sys.argv[1], sys.argv[2], sys.argv[3])
host = sys.argv[1]
port = int(sys.argv[2])
file = sys.argv[3]
try:
# Instaniating socket object
s = socket(AF_INET, SOCK_STREAM)
# Getting ip_address through host name
host_address = gethostbyname(host)
# Connecting through host's ip address and port number using socket object
s.connect((host_address, port))
sel1.register(
sock,
selectors.EVENT_READ, data = None)
fileToSend = open("file.txt", "rb")
data = fileToSend.read(1024)
while data:
print("Sending...")
fileToSend.close()
s.send(b"Done")
print("Done Sending")
print(s.recv(1024))
s.shutdown(2)
s.close()
except:
# Returning False in case of an exception
sys.stderr.write("Connection Failed")
Do the writing in a loop. There's no particular reason to chop it into 1024-byte pieces; the network stack will handle that for you.
By the way, your "Done" signal is not a good idea, especially since you're writing a binary file that might very well contain the word "Done". Remember that TCP is a streaming protocol. The other end does not see the exact packets you're sending. That is, just because you send 1024 bytes and 4 bytes, the other end might see it as reads of 256 and 772 bytes.
# Instaniating socket object
s = socket(AF_INET, SOCK_STREAM)
# Getting ip_address through host name
host_address = gethostbyname(host)
# Connecting through host's ip address and port number using socket object
s.connect((host_address, port))
fileToSend = open("file.txt", "rb")
print("Sending...")
while True:
data = fileToSend.read(1024)
if not data:
break
s.send( data )
fileToSend.close()
s.send(b"Done")
print("Done Sending")
print(s.recv(1024))
s.close()
I have two programs, one for the client and one for the server. I am trying to establish an FTP connection between them to transfer files. The two programs connect okay and I get a confirmation from the server that it has connected to the client's ip, but I get no more output from either program.
Client:
# client.py
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 60000 # Reserve a port for your service.
s.connect((host, port))
with open('received_file', 'wb') as f:
print ('file opened')
while True:
print('receiving data...')
data = s.recv(1024)
print('data=%s', (data))
if not data:
break
# write data to a file
f.write(data)
f.close()
print('Successfully get the file')
s.close()
print('connection closed')
Server:
# server.py
import socket # Import socket module
port = 60000 # Reserve a port for your service.
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
print ('Server listening....')
while True:
conn, addr = s.accept() # Establish connection with client.
print ('Got connection from', addr)
data = conn.recv(1024)
print('Server received', repr(data))
filename='text.txt'
f = open(filename,'rb')
l = f.read(1024)
while (l):
conn.send(l)
print('Sent ',repr(l))
l = f.read(1024)
f.close()
print('Done sending')
conn.send('Thank you for connecting')
conn.close()
I receive this output from the server:
Server listening....
Got connection from ('192.168.56.1', 51059)
And this from the client:
file opened
receiving data...
But neither program moves past this stage. I'm not sure where in the code that the problem is coming from.
I am trying to implement to implement FTP where I want to send Filename to server from client, I have tried below code, when I give file name as myText.txt but server is receiving as 'b"myText.txt'"
Can you please help me how can I get rid of b ?
This is the output on server:
This is server code:
import socket # Import socket module
port = 60000 # Reserve a port for your service.
socketObj = socket.socket() #Create a socket object
host = socket.gethostname() # Get local machine name
socketObj.bind((host, port)) # Bind to the port
socketObj.listen(5) # Now wait for client connectionection.
print ('Server listening....')
while True:
connection, addr = socketObj.accept() # Establish connectionection with client.
print ('Got connectionection from', addr)
data = connection.recv(1024)
print('Server received request for FTS of',(data))
filename=(repr(data))
f = open(filename,'rb')
l = f.read(1024)
while (l):
connection.send(l)
print('Sent ',repr(l))
l = f.read(1024)
f.close()
print('Done sending')
connection.send(('Thank you for connectionecting').encode())
connection.close()
This is the client code
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 60000 # Reserve a port for your service.
s.connect((host, port))
fileNeeded = input("What File do you need, please enter the name:")
s.send(fileNeeded.encode())
fileToBeSaved = input("Enter file name to save requested file")
with open(fileToBeSaved, 'wb') as f:
print ('file opened')
while True:
print('receiving data...')
data = s.recv(1024)
print((data))
if not data:
break
# write data to a file
f.write(data)
f.close()
print('Successfully got the file')
s.close()
print('connection closed')
The following is received in server:
Server received request for FTS of b'mytext.txt'
You can use the bytes.decode() method to convert bytes into a string:
Change:
filename=(repr(data))
to:
filename=repr(data).decode()
Probably a simple question for those who used to play with socket module. But I didn't get to understand so far why I can't send a simple file.
As far as I know there are four important steps when we send an info over a socket:
open a socket
bind
listen
accept ( possibly needed multiple times ).
Now, what I want to do is creating a file on my local machine and fill it with some info. ( been there, done that - all good so far )
Then, I create my client flow, which is the following:
s = socket.socket() # create a socket
s.connect(("localhost", 8081)) # trying to connect to connect over 8081 port
f = open("logs.txt", "rb+") # I'm opening the file that contains what I want
l = f.read(1024) # I'm reading that file
# I'm sending all the info from the file
while l:
s.send(l)
l = f.read(1024)
s.close()
Of course, firstly, I'm creating a server (at first, on my localhost) which will open that port and basically create the connection which will allow the byte-chunked data to be sent.
import socket
import sys
s = socket.socket() # create the socket
s.bind(("localhost", 8081)) # bind
s.listen(10)
while True:
sc, address = s.accept()
print sc, address
f = open('logs_1.txt', 'wb+') # trying to open a new file on the server ( which in this case is also my localhost )
while True: # write all the data to the file and close everything
l = sc.recv(1024)
f.write(l)
l = sc.recv(1024)
while l:
f.write(l)
l = sc.recv(1024)
f.close()
sc.close()
s.close()
Now, what doesn't work on my Ubuntu 14.10 machine:
the server part runs without error when doing python server.py
after the client script finishes writing some data in logs.txt and connects to the server, I get the following response on the server:
<socket._socketobject object at 0x7fcdb3cf4750> ('127.0.0.1', 56821)
What am I doing wrong ? The port is also different from the one that I set ( I also know that the port is not used - verifiet with nc ).
Can anybody explain me how to correctly treat this problem ?
I'm not sure what your second while True loop is for. Remove that, and it works as you expect:
import socket
import sys
s = socket.socket() # create the socket
s.bind(("localhost", 8081)) # bind
s.listen(10)
while True:
sc, address = s.accept()
print sc, address
f = open('logs_1.txt', 'wb+')
l = sc.recv(1024)
while l:
f.write(l)
l = sc.recv(1024)
f.close()
sc.close()
s.close()
I've successfully been able to copy the file contents (image) to a new file. However when I try the same thing over TCP sockets I'm facing issues. The server loop is not exiting. The client loop exits when it reaches the EOF, however the server is unable to recognize EOF.
Here's the code:
Server
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
f = open('torecv.png','wb')
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
print "Receiving..."
l = c.recv(1024)
while (l):
print "Receiving..."
f.write(l)
l = c.recv(1024)
f.close()
print "Done Receiving"
c.send('Thank you for connecting')
c.close() # Close the connection
Client
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.connect((host, port))
s.send("Hello server!")
f = open('tosend.png','rb')
print 'Sending...'
l = f.read(1024)
while (l):
print 'Sending...'
s.send(l)
l = f.read(1024)
f.close()
print "Done Sending"
print s.recv(1024)
s.close # Close the socket when done
Here's the screenshot:
Server
Client
Edit 1: Extra data copied over. Making the file "not complete."
The first column shows the image that has been received. It seems to be larger than the one sent. Because of this, I'm not able to open the image. It seems like a corrupted file.
Edit 2: This is how I do it in the console. The file sizes are the same here.
Client need to notify that it finished sending, using socket.shutdown (not socket.close which close both reading/writing part of the socket):
...
print "Done Sending"
s.shutdown(socket.SHUT_WR)
print s.recv(1024)
s.close()
UPDATE
Client sends Hello server! to the server; which is written to the file in the server side.
s.send("Hello server!")
Remove above line to avoid it.
Remove below code
s.send("Hello server!")
because your sending s.send("Hello server!") to server, so your output file is somewhat more in size.
You can send some flag to stop while loop in server
for example
Server side:
import socket
s = socket.socket()
s.bind(("localhost", 5000))
s.listen(1)
c,a = s.accept()
filetodown = open("img.png", "wb")
while True:
print("Receiving....")
data = c.recv(1024)
if data == b"DONE":
print("Done Receiving.")
break
filetodown.write(data)
filetodown.close()
c.send("Thank you for connecting.")
c.shutdown(2)
c.close()
s.close()
#Done :)
Client side:
import socket
s = socket.socket()
s.connect(("localhost", 5000))
filetosend = open("img.png", "rb")
data = filetosend.read(1024)
while data:
print("Sending...")
s.send(data)
data = filetosend.read(1024)
filetosend.close()
s.send(b"DONE")
print("Done Sending.")
print(s.recv(1024))
s.shutdown(2)
s.close()
#Done :)
The problem is extra 13 byte which server.py receives at the start. To resolve that write "l = c.recv(1024)" twice before the while loop as below.
print "Receiving..."
l = c.recv(1024) #this receives 13 bytes which is corrupting the data
l = c.recv(1024) # Now actual data starts receiving
while (l):
This resolves the issue, tried with different format and sizes of files. If anyone knows what this starting 13 bytes refers to, please reply.
Put file inside while True like so
while True:
f = open('torecv.png','wb')
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
print "Receiving..."
l = c.recv(1024)
while (l):
print "Receiving..."
f.write(l)
l = c.recv(1024)
f.close()
print "Done Receiving"
c.send('Thank you for connecting')
c.close()
you may change your loop condition according to following code, when length of l is smaller than buffer size it means that it reached end of file
while (True):
print "Receiving..."
l = c.recv(1024)
f.write(l)
if len(l) < 1024:
break