11. Network Programming-tcp File Downloader

Keywords: socket Mobile vim network

Example: Download something with Thunder. Before downloading, a file will be built locally and renamed after downloading.When the client downloads something, it receives part of the data from the server to write into the file just now, and then writes in again. When all the data is written, it means the download is complete.The essence is copying jobs.

There are two parts to download:
The server is the sender and the client is the downloader.
.
Client download process:
1. Downloads must have a network, there must be socket sockets
2. Download connet from server
3. How to let the server know what to download and pass the file name to the server send
4. The server reads out the contents of the file to the client, and the client completes the download by placing the recv revenue data in the file

with Explanation:
f = open("xxx")#You don't care how you open it here
f.write() or f.read()
f.close()
Above, if there are no exceptions when opening, but there are exceptions when reading, processing f.close() in except requires expanding excpt with try, but file reading and writing are common, try except is more complex.
That is, the code is as follows:

f = open("xxx") # I don't care how to open it here
try:
	f.write()perhaps f.read()
except:
	f.close()

The above code can be replaced with one sentence:
(One of the great features of with is that you don't need to write close, even if there are exceptions in reading and writing, you will call close)

with open("xxxx") as f:
	f.write()perhaps f.read()

vim 08-File Download-client.py

Process Setup Framework

def main():
	#1. Create Sockets
	#2. Bind server IP port
	#3. Linked Server
	#4. Get the downloaded file name
	#5. Send file name to server
	#6. Receive data from files
	#7. Save received data to a file
	#8. Close socket


if __name__ == "__main__":
	main()

Complete Code

Code parsing:
.
with open('[new]'+ download_file_name,'wb') as f:
... f.write(recv_data)
.
A string + a string for stitching, that is, the first parameter is the file name
.
The second "w" means open in W mode, and "w b" means binary mode, because the data recv receives is binary and is thrown in directly with B without decoding and encoding
.
f.write(recv_data) means to write recv_data content in

import socket

def main():
	#1. Create Sockets
	tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	#2. Get server IP port
	dest_ip = input("Please enter the server you want to download ip: ")
	dest_port = int(input("Please enter the server you want to download port: "))
	#3. Linked Server
	#The parameter after connect is a tuple
	tcp_socket.connect((dest_ip,dest_port))
	#4. Get the downloaded file name
	download_file_name = input("Please enter the name of the file you want to download:")
	#5. Send file name to server
	tcp_socket.send(download_file_name.encode("utf-8"))
	#6. Receive data from files
	recv_data = tcp_socket.recv(1024) # 1024=1K,1024*1024=1M,1024*1024*1024=1G
	#7. Save received data to a file
	with open("[new]"+download_file_name,"wb") as f:
		f.write(recv_data)
	#8. Close socket
	tcp_socket.close()


if __name__ == "__main__":
	main()

No problem after testing, write the server's code.

vim 09-File Download-server.py
Change the server's code directly before copying
cp 05-tcp server.py 09 File Download-server.py**

Code parsing:
#5, name of file to download from receiving client
file_name = new_client_socket.recv(1024).decode("utf-8")
print("Client (s%) file s to download are: s%"% (str(client_addr),file_name))
decode and recv concatenation, file_name is now a real string
Format and print the incoming client address and requested file name

import socket

def main():
	#1. Buy a mobile phone (create a socket)
	tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	
	#2. Plug in your mobile card (bind ip port)
	tcp_server_socket.bind(("",7890))
	
	#3. Set to ring state (change socket from active to passive listen)
	tcp_server_socket.listen(128)
	
	#4. Wait for someone to come in (wait for the customer to link to accept)
	new_client_socket,client_addr = tcp_server_socket.accept()
	
	#5. The name of the file to be downloaded from the receiving client
	file_name = new_client_socket.recv(1024).decode("utf-8")
	print("Client ( s%)The files you need to download are: s%" % (str(client_addr),file_name))
	
	#6. Send file data to client
	new_client_socket.send("hahahh".encode("utf-8"))

	#7. Close socket
	new_client_socket.close()
	tcp_server_socket.close()
	
if __name__ == "__main__":
main()

Then you can test it with the 08-file download-client.py client program and the 09-file download-server.py server program you just wrote. You can open both terminals at the same time to run the program

The download file data that the server just returned to the client is a test string, hahaha. Here's the real file to transfer to the past

Ideas:
Find a variable file_content instead of hahaha ha, as long as the file_content is the data read from the file.

import socket

def main():
	#1. Buy a mobile phone (create a socket)
	tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	
	#2. Plug in your mobile card (bind ip port)
	tcp_server_socket.bind(("",7890))
	
	#3. Set to ring state (change socket from active to passive listen)
	tcp_server_socket.listen(128)
	
	#4. Wait for someone to come in (wait for the customer to link to accept)
	new_client_socket,client_addr = tcp_server_socket.accept()
	
	#5. The name of the file to be downloaded from the receiving client
	file_name = new_client_socket.recv(1024).decode("utf-8")
	print("Client ( s%)The files you need to download are: s%" % (str(client_addr),file_name))
	
	#6. Send file data to client
	#new_client_socket.send("hahahh".encode("utf-8"))
	new_client_socket.send(file_content)
	#7. Close socket
	new_client_socket.close()
	tcp_server_socket.close()
	
if __name__ == "__main__":
main()

Ideas:
Now modern code becomes a bit complex, so a new function, send_file_2_client, is defined to
Usually 2 is used instead.
Client code is then cut below the newly defined function to receive the file name and return data sent by the client
Looking at the new function, the socket, new_client_socket, is used, so at the bottom, when calling the new function send_file_2_client, pass the new_client_socket over, and the client_addr over, as well as the formal parameters to be fully defined in the new function.
.
Reasons for creating a new function on its own: specific, stand-alone functions, get the name of the file to download, send download data to the client

import socket


def send_file_2_client(new_client_socket,client_addr):
	#5. The name of the file to be downloaded from the receiving client
	file_name = new_client_socket.recv(1024).decode("utf-8")
	print("Client ( s%)The files you need to download are: s%" % (str(client_addr),file_name))
	
	#6. Send file data to client
	#new_client_socket.send("hahahh".encode("utf-8"))
	new_client_socket.send(file_content)

def main():
	#1. Buy a mobile phone (create a socket)
	tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	
	#2. Plug in your mobile card (bind ip port)
	tcp_server_socket.bind(("",7890))
	
	#3. Set to ring state (change socket from active to passive listen)
	tcp_server_socket.listen(128)
	
	#4. Wait for someone to come in (wait for the customer to link to accept)
	new_client_socket,client_addr = tcp_server_socket.accept()

	send_file_2_client(new_client_socket,client_addr)
	
	#7. Close socket
	new_client_socket.close()
	tcp_server_socket.close()
	
if __name__ == "__main__":
main()

Further improvement of the new send_file_2_client function

Ideas:
First, identify the steps to complete the code:
1. The name of the file to be downloaded from the receiving client
2. Open this file to read data
3. Send file data to client

1 and 3 code already exist, perfect the second step code to open this file, read data, it is not appropriate to use with at this time. With is the premise to ensure that the file is opened, if read and write problems can be called close normally, but if the file can not be opened at all, the program will collapse. With is tried when open has w, w meansWrite, create a new file, the new file will not fail to open.Previously, with with in the client, the file read from the server is written to a new file, now download the file from the server to read first, read the file is content, but this file does not necessarily exist, so it may not open successfully, at this time try

Step 2 Code Interpretation:
try:
f = open(file_name,"rb")
file_content = f.read()
f.close()
except Exception as ret:
.
.
f = open(file_name,'rb'), r is read, RB reads out and converts directly to binary without decoding
f.read() is to read the content and receive it with the variable file_content
except Exception as ret: When writing normally you should first look at the error type, but at this point there is only one exception: the file cannot be opened, so write directly to Exception

import socket


def send_file_2_client(new_client_socket,client_addr):
	#1. The name of the file to be downloaded from the receiving client
	file_name = new_client_socket.recv(1024).decode("utf-8")
	print("Client ( s%)The files you need to download are: s%" % (str(client_addr),file_name))
	
	#2. Open this file to read data 
	try:
		f = open(file_name,"rb")
		file_content = f.read()
		f.close()
	except Exception as ret:
		print("There are no files to download: s%" % file_name)
	
	#3. Send file data to client
	#new_client_socket.send("hahahh".encode("utf-8"))
	new_client_socket.send(file_content)

def main():
	#1. Buy a mobile phone (create a socket)
	tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	
	#2. Plug in your mobile card (bind ip port)
	tcp_server_socket.bind(("",7890))
	
	#3. Set to ring state (change socket from active to passive listen)
	tcp_server_socket.listen(128)
	
	#4. Wait for someone to come in (wait for the customer to link to accept)
	new_client_socket,client_addr = tcp_server_socket.accept()

	send_file_2_client(new_client_socket,client_addr)
	
	#7. Close socket
	new_client_socket.close()
	tcp_server_socket.close()
	
if __name__ == "__main__":
	main()

If a file can be opened in the server, then send data to the client. If the file cannot be opened, do not send. For perfection, add one step to determine if there is anything in the file read by the server.
Further code refinement:

Ideas:
Define a variable file_content =None first. Define it before reading. If the file can be opened and read out, the file_content will have content. If the file cannot be opened, the file_content =None; so make a judgment about if file_content before sending data in step 3

import socket


def send_file_2_client(new_client_socket,client_addr):
	#1. The name of the file to be downloaded from the receiving client
	file_name = new_client_socket.recv(1024).decode("utf-8")
	print("Client ( s%)The files you need to download are: s%" % (str(client_addr),file_name))
	
	#2. Open this file to read data 
	try:
		f = open(file_name,"rb")
		file_content = f.read()
		f.close()
	except Exception as ret:
		print("There are no files to download: s%" % file_name)
	
	#3. Send file data to client
	if file_content:
		#new_client_socket.send("hahahh".encode("utf-8"))
		new_client_socket.send(file_content)

def main():
	#1. Buy a mobile phone (create a socket)
	tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	
	#2. Plug in your mobile card (bind ip port)
	tcp_server_socket.bind(("",7890))
	
	#3. Set to ring state (change socket from active to passive listen)
	tcp_server_socket.listen(128)
	
	#4. Wait for someone to come in (wait for the customer to link to accept)
	new_client_socket,client_addr = tcp_server_socket.accept()

	#5. Call function to send file data to client
	send_file_2_client(new_client_socket,client_addr)
	
	#6. Close socket
	new_client_socket.close()
	tcp_server_socket.close()
	
if __name__ == "__main__":
	main()

In order for a program to serve multiple clients in the future, while True is required

import socket


def send_file_2_client(new_client_socket,client_addr):
	#1. The name of the file to be downloaded from the receiving client
	file_name = new_client_socket.recv(1024).decode("utf-8")
	print("Client ( s%)The files you need to download are: s%" % (str(client_addr),file_name))
	
	#2. Open this file to read data 
	try:
		f = open(file_name,"rb")
		file_content = f.read()
		f.close()
	except Exception as ret:
		print("There are no files to download: s%" % file_name)
	
	#3. Send file data to client
	if file_content:
		#new_client_socket.send("hahahh".encode("utf-8"))
		new_client_socket.send(file_content)

def main():
	#1. Buy a mobile phone (create a socket)
	tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	
	#2. Plug in your mobile card (bind ip port)
	tcp_server_socket.bind(("",7890))
	
	#3. Set to ring state (change socket from active to passive listen)
	tcp_server_socket.listen(128)
	
	while True:
		#4. Wait for someone to come in (wait for the customer to link to accept)
		new_client_socket,client_addr = tcp_server_socket.accept()
	
		#5. Call function to send file data to client
		send_file_2_client(new_client_socket,client_addr)
		
		#6. Close socket
		new_client_socket.close()
	tcp_server_socket.close()
	
if __name__ == "__main__":
	main()

Then test each other with the client and server you just wrote, and find that the server is OK, but if the client downloads a file that is not in the server, the client will still download a new XXX.py file, but it will be empty when opened.So to debug the client's code,
vim 08-File Download-client.py Debugging Code

vim 08-File Download-client.py Add if judgment, if there is data to execute step 7 "Save received data to a file", that is, with
open('[new]'+ download_file_name,'wb') as f: f.write(recv_data) otherwise not executed

import socket

def main():
	#1. Create Sockets
	tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	#2. Get server IP port
	dest_ip = input("Please enter the server you want to download ip: ")
	dest_port = int(input("Please enter the server you want to download port: "))
	#3. Linked Server
	#The parameter after connect is a tuple
	tcp_socket.connect((dest_ip,dest_port))
	#4. Get the downloaded file name
	download_file_name = input("Please enter the name of the file you want to download:")
	#5. Send file name to server
	tcp_socket.send(download_file_name.encode("utf-8"))
	#6. Receive data from files
	recv_data = tcp_socket.recv(1024) # 1024=1K,1024*1024=1M,1024*1024*1024=1G
	if recv_data:
		#7. Save received data to a file
		with open("[new]"+download_file_name,"wb") as f:
			f.write(recv_data)
	#8. Close socket
	tcp_socket.close()


if __name__ == "__main__":
	main()

Posted by sing2trees on Mon, 12 Aug 2019 20:49:00 -0700