设为首页 加入收藏

TOP

Python套接字(一)
2017-09-30 14:11:18 】 浏览:416
Tags:Python 套接字

1、客户端/服务器架构

  什么是客户端/服务器架构?对于不同的人来说,它意味着不同的东西,这取决于你问谁以及描述的是软件还是硬件系统。在这两种情况中的任何一种下,前提都很简单:服务器就是一系列硬件或软件,为一个或多个客户端(服务的用户)提供所需的“服务”。它存在唯一目的就是等待客户端的请求,并响应它们(提供服务),然后等待更多请求。另一方面,客户端因特定的请求而联系服务器,并发送必要的数据,然后等待服务器的回应,最后完成请求或给出故障的原因。服务器无限地运行下去,并不断地处理请求;而客户端会对服务进行一次性请求,然后接收该服务,最后结束它们之间的事务。客户端在一段时间后可能会再次发出其他请求,但这些都被当作不同的事务。

2、客户端/服务器编程

2.1套接字

  套接字的起源可以追溯到20 世纪70 年代,它是加利福尼亚大学的伯克利版本UNIX(称为BSD UNIX)的一部分。因此,有时你可能会听过将套接字称为伯克利套接字或BSD 套接字。套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个进程)与另一个运行的程序进行通信。这就是所谓的进程间通信(Inter Process Communication,IPC)。有两种类型的套接字:基于文件的和面向网络的。UNIX 套接字是我们所讲的套接字的第一个家族,并且拥有一个“家族名字”AF_UNIX(又名AF_LOCAL,在POSIX1.g 标准中指定),它代表地址家族(address family):UNIX。包括Python 在内的大多数受欢迎的平台都使用术语地址家族及其缩写AF;其他比较旧的系统可能会将地址家族表示成域(domain)或协议家族(protocol family),并使用其缩写PF 而非AF。类似地,AF_LOCAL(在2000~2001 年标准化)将代替AF_UNIX。然而,考虑到后向兼容性,很多系统都同时使用二者,只是对同一个常数使用不同的别名。Python 本身仍然在使用AF_UNIX。因为两个进程运行在同一台计算机上,所以这些套接字都是基于文件的,这意味着文件
系统支持它们的底层基础结构。这是能够说得通的,因为文件系统是一个运行在同一主机上的多个进程之间的共享常量

  第二种类型的套接字是基于网络的,它也有自己的家族名字AF_INET,或者地址家族:因特网。另一个地址家族AF_INET6 用于第6 版因特网协议(IPv6)寻址。此外,还有其他的地址家族,这些要么是专业的、过时的、很少使用的,要么是仍未实现的。在所有的地址家族之中,目前AF_INET 是使用得最广泛的。

  Python 2.5 中引入了对特殊类型的Linux 套接字的支持。套接字的AF_NETLINK 家族允许使用标准的BSD 套接字接口进行用户级别和内核级别代码之间的IPC。针对Linux 的另一种特性(Python 2.6 中新增)就是支持透明的进程间通信(TIPC)协议。TIPC 允许计算机集群之中的机器相互通信,而无须使用基于IP 的寻址方式。Python 对TIPC 的支持以AF_TIPC 家族的方式呈现。

2.2套接字地址:主机-端口对

  有效的端口号范围为0~65535(尽管小于1024 的端口号预留给了系统)。

2.3面向连接的套接字

  TCP 套接字,必须使用SOCK_STREAM 作为套接字类型。

2.4无连接的套接字

  实现这种连接类型的主要协议是用户数据报协议(更为人熟知的是其缩写UDP)。为了创建UDP 套接字,必须使用SOCK_DGRAM 作为套接字类型。

3、python中的网络编程

3.1socket 模块

socket模块属性

套接字创建:

socket(socket_family, socket_type, protocol=0)
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ud pSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

socket对象方法:

服务器创建:

ss = socket() # 创建服务器套接字
ss.bind() # 套接字与地址绑定
ss.listen() # 监听连接
inf_loop: # 服务器无限循环
cs = ss.accept() # 接受客户端连接
comm_loop: # 通信循环
cs.recv()/cs.send() # 对话(接收/发送)
cs.close() # 关闭客户端套接字
ss .close() # 关闭服务器套接字#(可选)

为服务器实现一个智能的退出方案时,建议调用close()方法。

客户端创建:

cs = socket() # 创建客户端套接字
cs.connect() # 尝试连接服务器
comm_loop: # 通信循环
cs.send()/cs.recv() # 对话(发送/接收)
cs .close() # 关闭客户端套接字

 I/O多路复用

多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行(比如使用线程池)。 这样在处理1000个连接时,只需要1个线程监控就绪状态,对就绪的每个连接开一个线程处理就可以了,这样需要的线程数大大减少,减少了内存开销和上下文切换的CPU开销。

举一个例子,模拟一个tcp服务器处理30个客户socket。

假设你是一个老师,让30个学生解答一道题目,然后检查学生做的是否正确,你有下面几个选择:

1. 第一种选择: 按顺序逐个检查,先检查A,然后是B,之后是C、D。。。这中间如果有一个学生卡主,全班都会被耽误。
这种模式就好比,你用循环挨个处理socket,根本不具有并发能力。
2. 第二种选择:你 创建30个分身,每个分身检查一个学生的答案是否正确。 这种类似于为每一个用户创建一个进程或者线程处理连接。
3. 第三种选择,你 站在讲台上等,谁解答完谁举手。这时C、D举手,表示他们解答问题完毕,你下去依次检查C、D的答案,然后继续回到讲台上等。此时E、A又举手,然后去处理E和A。。。
这种就是IO复用模型,Linux下的select、poll和epoll就是干这个的。将用户socket对应的fd注册进epoll,然后epoll帮你监听哪些socket上有消息到达,这样就避免了大量的无用操作。此时的socket应该采用 非阻塞模式
这样,整个过程只在调用select、poll、epoll这些调用的时候才会阻塞,收发客户消息是不会阻塞的,整个进程或者线程就被充分利用起来,这就是 事件驱动,所谓的reactor模式。

方法:

windows python
    提供: select
Mac Python:
    提供: select
Linux Python:
    提供: select、poll、epoll
 
select方法:
sele
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python学习笔记(一) 下一篇python 随机数详细使用,推到以及..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目