pythonsocketsftpftp-client

How to send multiple commands to FTP server with python 'socket'?


I'm trying to print file catalogue from FTP server. I have two sockets: first to send commands to the server, second to get requested data. To parse data, I want to send LIST command multiple times, but I don't know how to do this properly. Here is my code:

import socket

HOST = '[IP address]'
USERNAME = '[login]'
PASSWORD = '[password]'

sock_1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_1.connect((HOST, 21))
sock_1.recv(1024)
sock_1.send(f'USER {USERNAME}\r\n'.encode())
sock_1.recv(1024)
sock_1.send(f'PASS {PASSWORD}\r\n'.encode())
sock_1.recv(1024)

sock_1.send('PASV\r\n'.encode())

response_values = sock_1.recv(1024).decode('utf-8').split(',')
port_high = int(response_values[-2])
port_low = int(response_values[-1].replace(').\r\n', ''))
port = port_high*256 + port_low

sock_2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_2.connect((HOST, port))

# Works as expected.
sock_1.send('LIST\r\n'.encode())
print(sock_1.recv(4096))
print(sock_2.recv(4096))

# Here comes a problem.
sock_1.send('LIST\r\n'.encode())
print(sock_1.recv(4096))
print(sock_2.recv(4096))

And the output I get:

b'150 Here comes the directory listing.\r\n'
b'[a totally expected array of bytes that fits into the buffer entirely]'
b'226 Directory send OK.\r\n'
b''

I feel like I'm doing something wrong on a theoretical level, but since I'm new to socket programming, I can't figure what exactly.

I think I can just recreate the connection every time I want to send another command, but there must be a better solution.


Solution

  • I think I can just recreate the connection every time I want to send another command, but there must be a better solution.

    FTP has a control connection for all commands and a data connection for each command transferring data. So the control connection (sock_1 in your code) will be kept open, the data connection must be established new though for each new LIST command.

    Creating a new data connection means sending the PASV command, parsing the response to get the new server side address and connecting to this address and then (in case of LIST) reading all data from this data connection until the other side closes the connection (recv returns 0).

    None of this is actually specific to socket programming, instead it is how the FTP protocol is defined at the application layer - see RFC 959 for the details.