对 Python Socket 编程的初探

对于python网络编程来说,免不了要用到socket模块。下面主要分享一下个人对python socket的一些理解。

socket编程步骤

  1. 服务端创建一个socket,绑定地址和端口,然后监听端口上传入的连接,一旦有连接进来,就通过accept函数接收传入的连接。
  2. 客户端也是创建一个socket。绑定远程地址和端口,然后建立连接,发送数据。

服务端socket

下面通过一段实例代码来详细说明

服务端 socker_server.py

首先我们通过socket.getaddrinnfo函数将host/port转换成一个包含5元组的序列。这个5元组包含我们创建一个socket连接所需要的所有必要参数。返回的5元组分别是 (family, sockettype, proto, canonname, sockaddr)

family 地址簇,用与socket()函数的第一个参数。主要有以下几个

  1. socket.AF_UNIX 用与单一机器下的进程通信
  2. socket.AF_INET 用与服务器之间相互通信,通常都用这个。
  3. socket.AF_INET6 支持IPv6

sockettype socket类型,用与socket()函数的第二个参数,常用的有

  1. socket.SOCK_STREAM 默认,用于TCP协议
  2. socket.SOCK_DGRAM 用于UDP协议

proto 协议,用于socket()函数的第三个参数。 getaddrinnfo函数会根据地址格式和socket类型,返回合适的协议

canonname 一个规范化的host name。

sockaddr 描述了一个socket address .是一个二元组,主要用于bind()和connect()函数

接下来创建一个socket对象,传入getaddrinnfo函数返回的af,sockettype,proto。

然后绑定socket address

开启监听模式

listen函数会监听连接到socket上的连接,参数表示在拒绝连接之前系统可以挂起的最大连接队列数量为5。这些连接还没有被accept处理。数量不能无限大,通常指定5。

一旦我们监听到了连接,就会调用accept函数接收连接

accept函数返回一个二元组,conn是一个新的socket对象,用来接收和发送数据。addr表示另一端的socket地址。

接下来我们就可以用conn对象发送和接收数据了

这里我们接收到一个连接socket就会停止运行,所以如果要循环连接的话,将accept函数放入到一个死循环里。

客户端socket

客户端socket编程相对比较简单,通过connect和服务端建立连接之后,就可以相互通信了。socket_client.py如下

备注: 对于getaddrinfo函数,可以参考下http://baike.baidu.com/link?url=TOO9akvwu0BLqTRQKNC5NW6GgWTyuhXhAqHmKZOyoaqUub-2RP7LUUALaV-Kd_dZAWVDZS5z-uDvgXrHeMSg8N3YtY0h-iOVQuHgpUMiA7a 这个函数的作用是把协议相关性安全隐藏在这个底层库函数内部。应用程序只要处理由getaddrinfo函数返回的对象即可。

以上主要是针对TCP流数据的socket编程。对于UDP协议的数据,处理略有不同。譬如发送接收UDP数据包处理函数为:

其他详细内容可以参考 http://python.usyiyi.cn/translate/python_278/library/socket.html

SocketServer模块

python中网络编程除了socket模块还提供了SocketServer模块,这一模块主要是对socket模块进行了封装,将socket的对象的创建,绑定,连接,接收,发送,关闭都封装在里面,大大简化了网络服务的编程。

此模块提供了以下2个主要的网络服务类,用于创建相应的套接字流

  1. TCPServer 创建TCP协议的套接字流
  2. UDPServer 创建UDP协议的套接字流

我们有了套接字流对象,还需要一个请求处理类。SocketServer模块提供了请求处理类有BaseRequestHandler,以及它的派生类StreamRequestHandler和DatagramRequestHandler。所以只要继承这3个类中的一个,然后重写handle函数,此函数将用来处理接收到的请求。下面看一个服务端的代码示例

看着是不是代码简单了很多,而且SocketServer模块内部使用了多路复用IO技术,可以实现更好的连接性能。看serve_forever函数的源代码用到了select模块。通过传入socket对象调用select.select()来监听socket对象的文件描述符,一旦发现socket对象就绪,就通知应用程序进行相应的读写操作。源代码如下:

即使使用了select技术,TCPServer,UDPServer处理请求仍然是同步的,意味着一个请求处理完,才能处理下一个请求。但SocketServer模块提供了另外2个类用来支持异步的模式。

  1. ForkingMixIn 利用多进程实现异步
  2. ThreadingMixIn 利用多线程实现异步

看名字就知道用mixin模式来实现异步。而mixin模式可以通过多继承来实现,所以通过对网络服务类进行多继承的方式就可以实现异步模式

针对ThreadindMixIn,实现异步的原理也就是在内部对每个请求创建一个线程来处理。看源码

下面提供一个异步模式的示例

更多对SocketServer模块的了解参考https://docs.python.org/2/library/socketserver.html  本文所使用的示例就来自官网。毕竟官网的例子实在太好了。

以上是本人对socket相关的理解,有什么不当或错误之处,还请指出。

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

1 6 收藏 评论

关于作者:oliver_lv

一只在原野中奔跑的程序猿,混迹于众猿之中,偶尔咆哮下刷刷存在感 个人主页 · 我的文章 · 11 ·    

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部