通过TCP可以实现网络间字符的发送和接收,既然可以实现网络的收发,那么自然可以实现文件的下载,市场上主流的下载器均使用socket实现网络通信。进行文件的远程传送。本项目应用场景,是作者经过学习网络通信原理为了实现虚拟机和主机进行实现文件的传送而开发的应用程序,十分的方便可以实现文件的传送和接收,因为作者虚拟机的Linux主机有的时候会很卡顿,莫名的bug。。。。。因此我通常在Windows主机写好代码最开始最笨的方法是通过U盘来实现文件的迁移,但是效率太低了,通过开发这个应用程序可以非常方便的实现数据的收发,下面介绍一下服务端和客户端的代码实现逻辑,代码如人生,逻辑亦如生活,这是我对python最真实的理解
下载文件:
服务端(服务器消息的收发)
import socket
def main():
#1.创建套接字
tcp_socket =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#2.获取服务器的IP和port
dest_ip =input("请输入下载服务器的IP")
dest_port =int(input("请输入端口"))
#3.链接服务器
tcp_socket.connect((dest_ip,dest_port))
#4.获取下载的文件名字
download_file_name =input("请输入要下载的文件名字")
#5.将文件名字发送到服务器
tcp_socket.send(download_file_name.encode("utf-8"))
#6.接受文件中的数据
recv_data = tcp_socket.recv(1024*1024) #1024 ---> 1k 1024*1024 --.1M
#7.保存并接受到的数据进入一个文件中
with open("[新]"+download_file_name,"wb") as f:
f.write(recv_data)
#8.关闭套接字
tcp_socket.close()
if __name__ == '__main__':
main()
客户端(请求)
import socket
def main():
# 1.买个手机(创建套接字 socket)
# 这个套接字用来初始化响应,最终需要最后新定义的套接字进行真正的实现通信
tcp_server_scoket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.插入手机卡(绑定本地信息 bind)
tcp_server_scoket.bind(("", 7890))
# 3.将手机设为正常的响铃模式(让默认的套接字有主动变为被动 listen)
tcp_server_scoket.listen(128)
# 4.等待别人电话到来(等待客户端的链接 accpet)
new_client_socket, client_addr = tcp_server_scoket.accept()
# 接收客户端发过来的请求
file_name =new_client_socket.recv(1024).decode("utf-8")
print("客户端(%s)需要下载的文件是:%s"%(str(client_addr),file_name))
#发送数据
new_client_socket.send("hhhhhhh--ok".encode("utf-8"))
new_client_socket.close()
tcp_server_scoket.close()
if __name__ == '__main__':
main()
我们通过简单的测试可以看到主机可以进行简单的网络通信,代码测试没有问题,由于我们做的这个数据只是一个测试代码,收发的是字符,但是在开发生产的时候我们更多的是收发文件,而并非字符串,这里我们需要对代码进行深入改造并且传递。
改造后
服务器服务端:
import socket
#服务器
def send_file2_client(new_client_socket,client_addr):
# 接收客户端发过来的请求
file_name = new_client_socket.recv(1024).decode("utf-8")
print("客户端(%s)需要下载的文件是:%s" % (str(client_addr), file_name))
#打开这个文件,读取数据
file_content =None
try:
f =open(file_name,"rb")
file_content = f.read()
f.close()
except Exception as ret:
print("没有要下载的文件!")
#3.发送文件的数据的客户端
if file_content:
# 发送数据
new_client_socket.send(str(file_name).encode("utf-8"))
def main():
# 1.买个手机(创建套接字 socket)
# 这个套接字用来初始化响应,最终需要最后新定义的套接字进行真正的实现通信
tcp_server_scoket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.插入手机卡(绑定本地信息 bind)
tcp_server_scoket.bind(("", 7890))
# 3.将手机设为正常的响铃模式(让默认的套接字有主动变为被动 listen)
tcp_server_scoket.listen(128)
while True:
# 4.等待别人电话到来(等待客户端的链接 accpet)
new_client_socket, client_addr = tcp_server_scoket.accept()
#调用发送文件函数,完成为客户段服务
send_file2_client(new_client_socket,client_addr)
#关闭套接字
new_client_socket.close()
tcp_server_scoket.close()
if __name__ == '__main__':
main()
客户客户端:
import socket
def main():
# 1.创建套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.获取服务器的IP和port
dest_ip = input("请输入下载服务器的IP")
dest_port = int(input("请输入端口"))
# 3.链接服务器
tcp_socket.connect((dest_ip, dest_port))
# 4.获取下载的文件名字
download_file_name = input("请输入要下载的文件名字")
# 5.将文件名字发送到服务器
tcp_socket.send(download_file_name.encode("utf-8"))
# 6.接受文件中的数据
recv_data = tcp_socket.recv(1024 * 1024) # 1024 ---> 1k 1024*1024 --.1M
# 7.保存并接受到的数据进入一个文件中
if recv_data:
with open("[新]" + download_file_name, "wb") as f:
f.write(recv_data)
# 8.关闭套接字
tcp_socket.close()
if __name__ == '__main__':
main()
listen(128)
意义就是可以支持很大的值,支持很多人同时请求。
TCP注意点:
- TCP服务器一般情况下都需要绑定,否则客户端找不到内容
- TCP客户端一般不绑定,因为主动链接服务器,所以只要绑定号服务器的IP,port等信息就行,本地客户端可以随机
- TCP 服务器中通过listen可以将socket创建出来的主动套接字变为被动套接字
- 当客户端需要链接服务器时,就需要使用connect进行链接,udp是不需要连接的,可以直接进行发送,但是TCP必须进行链接,只有连接成功才能进行通信,因此业界常用TCP进行通信,因为他更加的安全
- 当一个TCP客户端链接服务器时,服务端就会有一个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端进行服务
- listen后接的套接字时被动套接字,用来接受新的客户端的连接请求的,而accept返回新的套接字是用来编辑这个客户端的
- 关闭listen后的套接字一位置被动套接字关闭了,导致新的客户端就不能够链接服务器,但是之前已经连接成功的客户端正常通信
- 关闭accept返回的套接字意味着这个客户端已经服务完毕
- 当客户端的套接字调用close后,反无端会recv解阻塞,并且返回长度为0,因此,服务器可以通过返回数据的长度来进行判断客户端是否下线。
对比记忆:
-
udp通信构建流程:(收数据时候必须要绑定端口)
- socket初始化创建套接字
- bind绑定端口和ip
- sendto/recvfrom 收消息和发消息
- close 关闭套接字
-
TCP通信构建流程(严格区分服务端和客户端)(必须绑定端口)
- socket初始化创建套接字
- connect() 链接服务器
- send/recv 收消息和发消息
- close 关闭套接字
作者经过反复修改和测试,程序可以顺利的正常运行。
源码已上传至GitHub 有需要的可以下载来进行使用,如有需要封装成Linux可执行文件或Windows可执行文件可以联系作者!学富五车,七步成章。
下载入口 https://github.com/hunter137/socket_demo