python实现tcp协议,Python网络通信

  python实现tcp协议,Python网络通信

  在我们的日常生活和工作中,经常会接触到网络传播的内容。无论你是普通用户,还是通信行业的开发者,都无法避免与网络通信打交道。在我最初学习python的过程中,总结了python的网络通信问题,所以写了这篇文章作为记录,希望能给其他初学者一些指导和启发。本文的主要内容如下:

  1.在深入讲解之前,先介绍一些背景信息;

  2.引入套接字的概念;

  3.展示如何使用Python实现简单的web应用程序。

  客户端/服务器架构(C/S架构)什么是客户端/服务器架构?一般来说,特定对象和客户机或服务器之间没有严格的区别。区分的标准是在网络通信过程中,对象的行为模式决定了它是客户端还是服务器。

  服务器:为一个或多个客户机(用户)提供所需“服务”的一系列硬件或软件。工作流可以简单概括为:等待一个请求,响应并提供服务,等待下一个请求。

  客户端:为特定请求联系服务器、接收服务和处理相关事务的一方。客户端可以继续向服务器发送请求,也可以在事务请求完成后停止发送请求。

  互联网上典型的C/S架构的通信端点和套接字,在服务器请求对应的客户端之前,需要做一系列的准备工作。首先,你需要创建一个通信端点,通过它服务器可以监听客户端的请求(当然,在实际的网络通信中,会使用不同类型的通信端点来处理不同类型的消息,从而进行区分)。

  在网络通信中,一个常用的通信端点是套接字。在通信开始之前,网络应用程序需要创建套接字。

  插座的分类。基于文件的套接字

  UNIX是我们说的第一个套接字家族,有一个“家族名”:AF_UNIX(也称为AF_LOCAL,在POSIX1.g标准中指定),代表地址家族):UNIX。

  大多数流行的平台,包括Python,都使用地址族这个术语及其缩写AF;其他较旧的系统可能将地址族表示为域或协议族,并使用其缩写PF而不是AF。同样,AF _ LOCAL(2000年到2001年标准化)将取代AF_UNIX。但是,考虑到向后兼容性,许多系统同时使用这两者,但是对同一个常量使用不同的别名。Python本身还在用AF_UNIX。

  2.面向网络的套接字

  它也有自己的姓AF_INET,或者地址family: Internet。另一个地址系列AF_INET6用于IPv6寻址。(还有其他的地址族,要么专业,要么过时,要么很少用,要么还没实现。在所有的地址族中,AF_INET是目前使用最广泛的。

  一般来说,Python只支持AF_UNIX、AF_NETLINK、AF_TIPC和AF_INET家族。在下面的内容中,我们将使用AF_INET。

  Socket地址:Host-Port Pair就像我们在现实生活中打电话一样,socket通信需要一些标记来作为识别功能。当我们打电话时,通过区号和电话号码的组合,我们可以找到我们想要呼叫的用户;在套接字通信中,我们通过主机-端口对找到通信对象。

  众所周知,通过url或ip地址,我们可以在互联网中找到特定的主机。在每台主机中,不同的端口号将用于不同的通信目的。只要确定了主机和端口号,就可以在网络中唯一确定一个“通信端点”,即找到要通信的套接字的地址。

  需要注意的是,有效端口号范围为0 ~ 65535(小于1024的端口号为系统预留)。一般来说,我们可以根据实际需要使用其他端口号。

  面向连接的套接字和无连接的套接字1。面向连接的套接字(TCP)

  也称为虚拟电路或流式套接字。提供主要是序列化的、可靠的、不重复的数据,可以将消息拆分成多个片段,保证每个片段顺利到达目的地,然后将它们按顺序组合,最后将完整的消息交付给等待的应用程序。

  实现的主要协议是传输控制协议(TCP)。创建TCP套接字时,必须使用SOCK_STREAM作为套接字类型。

  2.无连接套接字(UDP)

  也称为数据报类型套接字。在传输过程中,其顺序性、可靠性和可重复性无法得到保证。事实上,发送的消息可能不会到达末尾,也可能有重复的消息。

  我们继续使用数据报的原因与面向连接的套接字有关。因为维护TCP连接需要大量的开销,所以发送数据报可以确保成本更低,所以它通常提供更好的性能,并且可能更适合某些类型的应用程序。

  实现的主要协议是用户数据报协议(UDP)。要创建UDP套接字,必须使用SOCK_DGRAM作为套接字类型。

  网络编程socket()模块函数在Python中创建一个socket,必须使用socket.socket()函数,其一般语法如下:

  套接字(套接字系列,套接字类型,协议=0)

  其中socket_family为AF_UNIX或AF_INET,socket_type为SOCK_STREAM或SOCK_DGRAM,协议通常省略,默认值为0。

  在python编程中,我们首先在文件的开头引用所需的模块。在这里,我们使用“从套接字导入*”。通过这样的引用,我们可以如下直接创建一个套接字:

  tcpSock=socket(AF_INET,SOCK _ STREAM)UDP SOCK=socket(AF _ INET,SOCK_DGRAM)

  成功创建socket后,我们可以调用socket对象的内置方法进行其他操作。详见python的文档。

  TCP 1。创建TCP服务器

  下面是一个TCP服务器程序,它接受客户端发送的字符串,给它加上时间戳,然后将其返回给客户端。事不宜迟,先贴出代码:

  TCP时间戳服务器第1 ~ 4行:

  声明运行环境,导入socket模块和time.ctime()。

  第6 ~ 10行:

  指定主机地址、工作端口号和接收缓存的长度。和主机端口一起构成了ADDR,它反映了上面提到的“主机端口对”。服务器的主机是空的,这意味着它可以使用任何可用的地址。

  第12 ~ 14行:

  创建一个套接字,将套接字绑定到服务器地址,并启动TCP监控。

  第16 ~ 32行:

  进入服务器的无限循环,等待接收客户端的连接。在第18行中,我们通过accept()获得了客户端的tcpCliSock和addr,因此我们可以使用这个tcpCliSock来专门处理客户端的事务(从而将其与其他请求客户端区分开来)。在第22行,使用recv()接收消息。如果消息为空,则跳出循环,关闭当前客户端的连接,然后继续等待连接;如果没有,解析消息,添加时间戳,重新编码成ASCII字节,通过send()发送回客户端。在这个程序中,第32行不会被执行,只是用来提醒程序员在使用这个程序时,一定要考虑合理科学的退出方法,正确调用close()方法。

  这里需要强调的是,由于python的编码问题,我们的消息只有在主机端解码(如decode())后才能正确显示,只有在编码(如encode()、bytes())后才能发送到网络端。无论是在服务器还是在客户端,我们都需要考虑这种情况。

  2.创建TCP客户端

  创建客户机比创建服务器简单得多。与客户机服务器建立连接,向服务器发送一个字符串,从服务器接收带有时间戳的消息并打印出来。发送一个空字符串来关闭套接字并退出此连接。代码示例如下:

  TCP时间戳客户端行1 ~ 3:

  声明运行环境并导入socket模块。

  第5 ~ 9行:

  指定主机地址、工作端口号和接收缓存的长度。和主机端口一起构成了ADDR,它反映了上面提到的“主机端口对”。这里主机是服务器所在主机的地址。因为我在本地进行了通信测试,所以地址被设置为127.0.0.1(localhost)。在实际的网络沟通中,根据具体情况进行相应的修改。客户端填充的端口必须对应服务器填充的端口,才能正常通信。

  第11 ~ 12行:

  创建一个套接字,主动调用它并通过connect()连接到服务器。

  第14 ~ 25行:

  无限循环:客户端填写要发送的消息,发送后等待接收服务器的回复,收到结果后打印结果。当客户端输入的内容为空,或者服务器断开连接,客户端接收失败时,退出循环,调用close()函数关闭客户端的套接字。

  同样,在发送消息之前,我们需要对数据进行编码,接收到的结果也需要解码后才能正常显示。如果我们想把代码改成对应的ipv6形式,只需要把HOST改成“:1”,sock_family改成AF_INET6。

  UDP通信1。创建UDP服务器

  UDP服务器的功能和TCP基本相同。主要区别在于UDP服务器不是面向连接的,所以它只需要等待客户端的请求并回复消息。不需要将成功连接的客户端“转换”到独立的套接字。示例代码如下:

  UDP服务器第1 ~ 4行:

  声明运行环境,导入socket模块和time.ctime()。

  第6 ~ 10行:

  与TCP相同,指定主机地址、工作端口号和接收缓存长度。和主机端口一起构成了ADDR,它反映了上面提到的“主机端口对”。服务器的主机是127.0.0.1,这意味着它使用本地主机地址。

  第12 ~ 13行:

  创建一个socket,将socket绑定到服务器地址,绑定后直接等待接收,无需监控。

  第15 ~ 24行:

  进入服务器的无限循环,等待接收客户端的连接。第17行使用recvfrom()接收消息,同时获取通信客户端的地址对信息。然后解析消息,添加时间戳,重新编码成ASCII字节,通过sendto()发送回客户端。此时,因为服务器不保持与客户端的连接,所以需要指定要发送的地址对信息。同样,在这个程序中,第24行也不会被执行。只是用来提醒程序员在使用这个程序时,一定要考虑合理科学的退出方法,正确调用close()方法。

  2.创建UDP客户端

  原理很简单。上面提到了,就不详细解释了。直接粘贴代码:

  UDP客户端关于服务器退出的问题。最后提到下面这个关于服务器出口的问题。在开发中,相对友好的退出方式是将服务器的while部分放在try-except try子句中,并监控EOFError和KeyboardInterrupt异常,这样服务器的套接字就可以在except或finally子句中关闭。

  参考文献:《Python核心编程(第三版)》【美】卫斯理春著,敏感的鸵鸟、李斌、mdhb译。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: