python 实战之模仿开发QQ聊天软件(三)TCP/IP服务器与客户端建设

Python 专栏收录该内容
7 篇文章 2 订阅

无论是p2p还是c/s还是b/s,只要用到通讯,必然是要用到今天写的这个。

python+MYSQL 在pycharm中的使用

TCP/IP是网络软件最核心的部分,缺少这个你只能当做单机游戏玩。

TCP/IP,只需要搞清楚udp和tcp这两个就可以了。

两者的区别在于

udp每次发送信息都需要发送ip和端口号,可以比作寄信,tcp只需要发送一次ip和端口号直到客户端运行结束,可以比作是打电话。

udp的保密性不好,所以在做通讯的时候基本选择tcp,这篇文章只提tcp

tcp客户端与服务器的工作模式如下图所示:

先解释一下ip,端口号,套接字都是什么意思:

打个比方: 朋友使用导航去你家找你玩,必然需要知道你住在哪里。

ip就是哪个街道哪个小区哪一撞哪一单元哪一层,端口号是哪一个门。

套接字就是他出发地和目的地,也就是说套接字是两个端点。

 

 

                                           客户端模型

import socket

                            1.使用socket创建套接字:

tcp_client_socket = socket.socket(socket.AF_INET,socekt.SOCK_STREAM)

socket(AF_INET,SOCK_STREAM)

AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合

流式Socket(SOCK_STREAM)是一种面向连接的Socket

                             2.使用connect()方法连接服务器

tcp_client_socket.connect(("192.168.0.1",8080))

("192.168.0.1",8080)是一个元组,首元素为服务器ip地址,字符型的,8080是服务器当前程序使用端口号,整型的

我的服务器和客户端是在同一个网段的,所以可以直接连接,不同网段需要使用交换机或者网线直连。(校园网wifi会组建内网,即使是同一个路由器也不行,网线直连后修改ip地址就可以了)

                             3.使用recv()、send()方法收发数据

recv_data = tcp_client_socket.recv(1024)  # 客户端接收服务器发来的信息最大长度为1K
data = recv_data.decode("utf-8")    #解码
tcp_client_socket.send("123".encode("utf-8))  # 客户端向服务器以utf-8的编码格式发送123

发送字符串的时候需要注意,如果是windows上运行的服务器编码格式是gbk,而linux,mac都是utf-8

                            4.使用close()方法关闭套接字

tcp_client_socket.close()

                                                   服务器模型

                                1.使用socket创建套接字

tcp_service_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

                                2.使用bind()绑定本地信息

tcp_service_socket.bind(("",8080))

                               3.使用listen()加入监听等待客户端接入

tcp_service_socket.listen(128)

                                 4.使用accept()为客户创建新套接字并读取用户ip和端口号

new_client_socket,client_addr = tcp_service_socket.accpet()

这个过程可能不太好理解,大概意思就是你打电话给10086,首先是打给10086的主机,然后主机分配一个话务员给你,帮你办理业务

                                 5.使用recv()/send()发送数据

new_client_socket.send()
recv_data = new.client_socket.recv(1024)

这个和客户端是没有区别的

                                6.关闭新套接字

new_client_socket.close()

相当于客服业务结束,挂断他所在的分机

                               7.关闭源套接字

tcp_service_socket.close()

 

 

 

样例:文件下载器

服务器主机ip 192.168.0.1 端口号 8081

客户端主机ip 192.168.0.2 端口由系统分配

客户端源代码

import socket

def main():
	# 创建套接字
	tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

	# 获取服务器的ip port
	# addr = ("192.168.0.1",8081)

	# 连接服务器
	tcp_socket.connect(("192.168.0.1",8081))

	# 获取下载文件名
	download_file_name = input("文件名")

	# 将文件名发送到服务器
	tcp_socket.send(download_file_name.encode("utf-8"))

	# 接受文件中的数据
	recv_data = tcp_socket.recv(1024*1024)
	
	if recv_data:
		# 保存接收的数据到文件中
		with open("[新]" + download_file_name,"wb") as f:
			f.write(recv_data)

	# 关闭套接字
	tcp_socket.close()

if __name__ == "__main__":
	main()

服务器源代码

import socket

def send_file_2_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("没有要下载的文件(%s)" % file_name)

    # 发送数据给客户端
    if file_content:
        # new_client_socket.send("hahahah".encode("utf-8"))
        new_client_socket.send(file_content)

def main():
   
    # 创建socket
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)


    # 绑定本地信息
    tcp_server_socket.bind(("",8081))

    # 加入监听套接字等待客户端连接
    tcp_server_socket.listen(128)

    while True:
        print("等待一个新客户端的到来")
        # 创建新套接字与客户端连接
        new_client_socket,client_addr = tcp_server_socket.accept()
        print("新客户端已经到来了:%s" % str(client_addr))

        # 发送文件
        send_file_2_client(new_client_socket,client_addr)
        
        # 关闭套接字
        new_client_socket.close()

    tcp_server_socket.close()

if __name__ == '__main__':
    main()

当然,目前这个只能完成单点操作,加入thread可以实现多任务模式

 

  • 3
    点赞
  • 2
    评论
  • 22
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值