前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 网络编程基础

Python 网络编程基础

作者头像
arcticfox
修改2019-06-26 19:39:07
9680
修改2019-06-26 19:39:07
举报

网络编程预备

在学习网络编程时,需要预先了解大量的概念,因此,对于没有任何基础的朋友,请先阅读本公众号内的【认识计算机】系列文章中的《5. 计算机与网络》教程后,再学习本章。

通常网络编程也被称为套接字(socket)编程,它最早可以追溯到 20 世纪 70 年代,在美国加利福尼亚大学的伯克利版本 UNIX系统(即BSD UNIX)上出现。

C/S架构

C指Client即客户端,S指Server 即服务端。C/S架构也就是所谓的客户端/服务端架构。简单来说,客户端也就是我们用户电脑上的程序,而服务端则是远程的用于接收、处理来自客户端发送的数据的程序。

因此我们知道,通常客户端和服务端并不是运行在一起的,但是由于实际情况的限制,我们今天要学习编写的程序,是使客户端和服务端运行在同一台电脑上的。

TCP协议

在之前的理论知识部分,我们已经知道,涉及到网络编程方面,基本就是和协议打交道了。现在我们要学习的第一个协议就是TCP协议。

TCP协议是一种面向连接的套接字。这意味着在进行通信之前必须先建立一个连接。TCP连接是基于字节流的,通过TCP连接传送的数据,无差错、不丢失、不重复,且按顺序到达。

TCP协议这种所谓的必须先建立连接才能通信的模型,非常像我们打电话的过程。我们打电话时,必须等到电话彻底接通后,才能开始讲话,否则在电话仍处于“嘟…嘟…”声时,我们讲话是没用的。与之相反的,则是一种无连接通信。大家可以回忆一下,曾经有一种通信工具叫BP机,或者俗称Call机,在中国香港老电影中还有见到。给对方BP机发送完信息后就结束了,并不需要对方的BP机处于开机状态,即使对方关机了,开机后也可以可以收到信息。

实际上真正最接近无连接通信的是电报机。如果大家喜欢看谍战影片,对于发电报应该不会陌生。发电报的人将电报发出去就结束了,如果此刻对方没有监听电报的无线信号,那么就错过了该电报,这意味着信息丢失,通信失败。因此电报通信的双方在通信前必须约定好时间,几点几分开始通信,然后一份电报要连续重复发送三遍,防止对方开小差,没监听到电报信号。

而面向连接的通信则不同,这就好比通信双方建立了一个类似水管的通道,数据就是水管中的水,只有通道建立成功之后,才会开闸放水,确保水流通畅。一旦水管断裂,立即宣告通信失败,并尝试重新建立通道,直到通道成功建立才再次通信。因此才说,面向连接的通信是可靠的,安全的,不会丢失数据的。

Python TCP网络编程

TCP客户端

创建client.py文件

代码语言:javascript
复制
 1  import socket
 2
 3  # 定义IP地址和端口号
 4  ip = '127.0.0.1'
 5  port = 8787
 6
 7  # 这里通过socket函数创建一个客户端套接字对象client_sock
 8  # AF_INET:用于指定地址族,这里是固定写法,它表示使用IPv4地址
 9  # SOCK_STREAM:表示指定使用TCP协议
10  client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
11
12  # 连接指定的IP地址和端口,创建一个TCP连接通道
13  client_sock.connect((ip, port))
14
15  # 向对方发送信息。TCP协议发送的是字节
16  # 因此需要先调用encode函数将字符串转为字节,才能发送出去
17  client_sock.send("Hello ,I'm client".encode())
18
19  # 关闭连接
20  client_sock.close()

直接运行上述代码会报错,因为没有服务端程序,无法建立连接

TCP服务端

创建server.py文件

代码语言:javascript
复制
 1  import socket
 2
 3  # 定义IP地址和端口号
 4  ip = '127.0.0.1'
 5  port = 8787
 6
 7  print("**** 服务端启动 ****")
 8
 9  # 创建服务端套接字对象
10  server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
11
12  # 绑定IP和端口号
13  server_sock.bind((ip, port))
14
15  # 开始监听IP和端口,设置最多接受5个客户端访问
16  server_sock.listen(5)
17
18  # 等待客户端来连接。accept函数会阻塞,即在此处暂停,直到有客户端连接才继续向下执行
19  # accept返回两个值,第一个是客户端对象,第二个是客户端的地址
20  client, addr = server_sock.accept()
21
22  print("来了一个新客户端:", addr[0])
23
24  # 从已连接的通道中读取1024字节大小的数据,即1K大小
25  data = client.recv(1024)
26
27  # TCP传送的是字节,因此调用decode函数将字节转为字符串
28  print(data.decode())
29
30  # 关闭连接
31  client.close()
32  server_sock.close()

在运行时需要注意,服务端和客户端是两个程序,这里建议使用命令行运行,而不要在IDE中运行代码。打开两个命令行窗口,首先用一个运行服务端程序,然后另一个运行客户端程序

可以看到,服务端成功收到了来自客户端发送的信息。

以上代码中,有几点需要特别说明一下

  1. 为什么要使用127.0.0.1做为IP地址? 127.0.0.1是一个特殊的IP地址,它是指本机网卡的回送IP地址,一般用于测试,大家一定要记住这个地址。其原理如下图

当然,如果大家有两台电脑,并且这两台电脑处于同一个局域网中,例如连接在同一个路由器上,那么就无需如此模拟,可以使用实际IP地址来验证程序。

  1. 端口号可以随便指定吗? 是的,你可以随便指定一个端口来通信,但是只能服务端程序来指定,客户端只管主动去连接服务端打开的端口。还记得我们在《5.计算机与网络》一文中说过的吗,服务器不会主动去连接客户端。但是有一点大家一定要注意,端口号建议指定5000以上的,因为5000以下的很多具有特殊意义,防止出现端口被占用的情况。

开发聊天程序

经过上面的学习,我们对TCP网络编程已经有了一定的理解,下面就让我做一点稍微复杂的程序,写一个单步的聊天程序。

编写服务端程序

代码语言:javascript
复制
 1  import socket
 2  import time
 3
 4  # 定义IP地址和端口号
 5  ip = '127.0.0.1'
 6  port = 8787
 7
 8  print("**** 服务端启动 ****")
 9
10  # 创建服务端套接字对象
11  server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
12
13  # 绑定IP和端口号
14  server_sock.bind((ip, port))
15
16  # 开始监听IP和端口,设置最多接受5个客户端访问
17  server_sock.listen(5)
18
19  # 等待客户端来连接。accept函数会阻塞
20  client, addr = server_sock.accept()
21  print("来了一个客户端:", addr[0])
22  client.send("!!!欢迎访问TCP服务器!!!".encode())
23
24  # 开启一个死循环,使服务器一直运行
25  while True:
26    # 从已连接的通道中读取1024字节大小的数据
27    data = client.recv(1024)
28
29    # 获取当前电脑的时间
30    this_time = time.strftime("%H:%M:%S")
31    print("from client:", this_time)
32    print(data.decode())
33
34    message = input("请输入:")
35    client.send(message.encode())
36
37  client.close()
38  server_sock.close()

编写客户端程序

代码语言:javascript
复制
 1  import time
 2  import socket
 3
 4  # 定义IP地址和端口号
 5  ip = '127.0.0.1'
 6  port = 8787
 7
 8  # 创建一个客户端套接字对象client_sock
 9  client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
10
11  # 连接指定的IP地址和端口,创建一个TCP连接通道
12  client_sock.connect((ip, port))
13
14  while True:
15    data = client_sock.recv(1024)
16
17    # 获取当前电脑的时间
18    this_time = time.strftime("%H:%M:%S")
19    print("from server:", this_time)
20    print(data.decode())
21
22    message = input("请输入:")
23    client_sock.send(message.encode())
24
25  client_sock.close()

我们已经说过,TCP通信,是首先建立一个连接通道,然后使用这个通道通信。既然是通道,那么在这个通道的两端,当然是既可以往通道里发数据,也可以从通道里面收数据了,这个通道是可以同时收发的。

打开两个命令行工具,运行以上代码后,会发现一个问题,那就是这个聊天工具是单步的,整个聊天过程是交替进行的,说完一句话必须等对方说,对方说完自己才能接着回。这是因为我们还没有学过并发,我们现在写的程序都是单步的,不能同时做多件事,以后学会了并发编程,再改造这个程序,就能实现收发自如了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程之路从0到1 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 网络编程预备
    • C/S架构
      • TCP协议
      • Python TCP网络编程
        • TCP客户端
          • TCP服务端
            • 开发聊天程序
              • 编写服务端程序
              • 编写客户端程序
          相关产品与服务
          命令行工具
          腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档