Sending a file over TCP sockets in Python - python

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

Related

Client and Server program stuck after creating FTP connection

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.

Python3 - [Errno 32] Broken Pipe while using sockets

I have the following code for the server:
import socket
import threading
def handle_client(client_socket):
request = client_socket.recv(1024)
print ("[*] Received: %s" % request)
client_socket.send("ACK!".encode("utf-8"))
client_socket.close()
bind_ip = "0.0.0.0"
bind_port = 9998
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((bind_ip, bind_port))
server.listen(5)
print ("[*] Listening on %s:%d" % (bind_ip, bind_port))
while True:
client, addr = server.accept()
print ("[*] Accepted connection from: %s:%d" % (addr[0], addr[1]))
client_handler = threading.Thread(target = handle_client, args = (client))
client_handler.start()
And the following on the client side:
def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((target, port))
if len(buffer) > 0:
client.send(buffer.encode("utf-8"))
data = client.recv(4096).decode("utf-8")
print(" - " + data)
while True:
buffer = input("Input:")
buffer += "\n"
client.send(buffer.encode("utf-8"))
data = client.recv(4096).decode("utf-8")
print (" - " + data)
The function client_sender is called by another function where I can choose if listen incoming connection or send data to someone.
I will call it in this way:
python3 filename.py -ip 0.0.0.0 -port 9998
I can then write some data. The first time I do it I press CTRL + D to send it and the server gets and the client gets the response.But when I try to send some data from inside the "While True" loop the server never gets it and I receive this:
client.send(buffer.encode("utf-8"))
BrokenPipeError: [Errno 32] Broken pipe
How do I solve it? The only solution I found that works is to move these two lines inside the "While True" loop:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((target, port))
However it seems inefficient to me to re-connect every time.
EDIT
As suggested by Sam Mason, changing the handle_client in the following way solves the problem:
def handle_client(client_socket):
while True:
request = client_socket.recv(1024).decode("utf-8")
if len(request):
print ("[*] Received: %s" % request)
client_socket.send("ACK!".encode("utf-8"))
else:
client_socket.close()
break
your server is closing the port immediately after a single recv. I'd suggest changing your handle_client code to have some sort of while loop that ends when recv returns an empty string (this indicates the client has shutdown their end of the connection, probably by closeing their connection)

sending multiple files in python

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

'b' is getting passed when sending string from client to server in python while trying FTP implementation

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

TCP client server not receiving any data from each other

I have written the following TCP client and server using python socket module. However, after I run them, no output is being given. It seems that
the program is not able to come out of the while loop in the recv_all method
Server:
import socket
def recv_all(sock):
data = []
while True:
dat = sock.recv(18)
if not dat:
break
data.append(dat)
return "".join(data)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '127.0.0.1'
PORT = 45678
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((HOST, PORT))
sock.listen(1)
print "listening at", sock.getsockname()
while True:
s, addr = sock.accept()
print "receiving from", addr
final = recv_all(s)
print "the client sent", final
s.sendall("hello client")
s.close()
Client :
import socket
def recv_all(sock):
data=[]
while True:
dat=sock.recv(18)
if not dat:
break
data.append(dat)
return "".join(data)
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
PORT=45678
HOST='127.0.0.1'
sock.connect((HOST,PORT))
sock.sendall("hi server")
final=recv_all(sock)
print "the server sent",final
Because in server file you use an endless loop in another. I suggest you to edit recv_all method in both files this way:
def recv_all(sock):
data = []
dat = sock.recv(18)
data.append(dat)
return "".join(data)
But after edit like this your server stays on until KeyInterrupt, while you should run client file everytime you want to send data. If you want an automatically send/receive between server and client, I offer you try threading.

Categories