服务器创建一个通信端点使服务器监听请求,客户端创建一个通信端点建立一个到服务器的连接
有两种类型的套接字:基于文件的和基于网络的
基于文件的套接字:两个进程运行在同一台计算机上
AF_UNIX(又名AF_LOCAL):代表地址家族(address family):UNIX
其他比较旧的系统可能会将地址家族表示成域(domain)或协议家族(protocol family),缩写PF
1) AF_INET:地址家族:因特网(最广泛)
AF_INET6:第6版因特网协议(IPV6)寻址
1) AF_NETLINK:无连接,允许使用标准的BSD(加利福尼亚大学的伯克利版本)套接字接口进行用户级别和内核级别代码之间的IPC(通信进程:Inter Process Communication)
2) AF_TIPC:支持透明的进程间通信协议,允许计算机集群之中的机器互相通信,而无需使用基于IP的寻址方式
一个网络地址由主机名和端口号对组成,有效的端口号范围为0~65535(小于1024的端口号预留给了系统)
不管采用的是哪种地址家族,都有两种不同风格的套接字连接(面向连接的套接字和无连接的套接字)
在进行通信之前必须先建立一个连接,实现这种连接类型的主要协议是传输控制协议(TCP),每条消息可以拆分成多个片段,并且每一条消息片段都确保能够到达目的地。
创建TCP 套接字,必须使用SOCK_STREAM 作为套接字类型(AF_INET套接字与TCP)
在通信开始之前并不需要建立连接,实现这种连接类型的主要协议是用户数据报协议(UDP),消息是以整体发送的。
创建UDP 套接字,必须使用SOCK_DGRAM 作为套接字类型(AF_INET套接字与UDP)
主要模块是socket 模块,在这个模块中可以找到socket()函数,该函数用于创建套接字对象
创建套接字,必须使用socket.socket()函数,它一般的语法如下:
socket(socket_family, socket_type, protocol=0)
其中,socket_family是AF_UNIX或AF_INET,socket_type是SOCK_STREAM或SOCK_DGRAM。protocol通常省略,默认为0。
例:
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
使用from socket import *,则:
tcpSock = socket(AF_INET, SOCK_STREAM)
名称
描述
服务器套接字方法
s.bind()
将地址(主机名、端口号对)绑定到套接字上
s.listen()
设置并启动TCP 监听器
s.accept()
被动接受TCP 客户端连接,一直等待直到连接到达(阻塞)
客户端套接字方法
s.connect()
主动发起TCP 服务器连接
s.connect_ex()
connect()的扩展版本,此时会以错误码的形式返回问题,而不是抛出一个异常
普通的套接字方法
s.recv()
接收TCP 消息
s.recv_into()
接收TCP 消息到指定的缓冲区
s.send()
发送TCP 消息
s.sendall()
完整地发送TCP 消息
s.recvfrom()
接收UDP 消息
s.recvfrom_into()
接收UDP 消息到指定的缓冲区
s.sendto()
发送UDP 消息
s.getpeername()
连接到套接字(TCP)的远程地址
s.getsockname()
当前套接字的地址
s.getsockopt()
返回给定套接字选项的值
s.setsockopt()
设置给定套接字选项的值
s.shutdown()
关闭连接
s.close()
关闭套接字
s.detach()
在未关闭文件描述符的情况下关闭套接字,返回文件描述符
s.ioctl()
控制套接字的模式(仅支持Windows)
面向阻塞的套接字方法
s.setblocking()
设置套接字的阻塞或非阻塞模式
s.settimeout()
设置阻塞套接字操作的超时时间
s.gettimeout()
获取阻塞套接字操作的超时时间
面向文件的套接字方法
s.fileno()
套接字的文件描述符
s.makefile()
创建与套接字关联的文件对象
数据属性
s.family
套接字家族
s.type
套接字类型
s.proto
套接字协议
1) 通用TCP服务器的一般伪代码
ss = socket() # 创建服务器套接字 s.bind() # 套接字与地址绑定 ss.listen() # 监听连接 inf_loop: # 服务器无限循环 cs = ss.accept() # 接受客户端连接 comm_loop: # 通信循环 cs.recv()/cs.send() # 对话(接收/发送) cs.close() # 关闭客户端套接字 ss .close() # 关闭服务器套接字#(可选)ss.bind()服务器需要绑定到一个本地地址和占用一个端口。ss.listen()监听(传入)的连接。
ss.accept()开启一个简单的(单线程)服务器等待客户端的连接,是阻塞的,意味着执行将被暂停,直到一个连接到达,一旦服务器接收了一个连接,就会返回(利用accept())一个独立的客户端套接字,用来与即将到来的消息进行交换(当一个传入的请求到达时,服务器会创建一个新的通信端口来直接与客户端进行通信,再次空出主要的端口,以使其能够接受新的客户端连接);
2) 创建TCP服务器代码
1 ''' 2 创建TCP服务器 3 ''' 4 5 from socket import * 6 from time import ctime 7 8 HOST = '' #空白表示可以使用任何可用的地址,是对bind()方法的标识 9 PORT = 21567 #端口 10 BUFSIZ = 1024 #缓冲区大小设置为1KB,可根据网络性能和程序需要改变这个容量 11 ADDR = (HOST,PORT) 12 13 tcpSerSock = socket(AF_INET,SOCK_STREAM) #创建套接字 14 tcpSerSock.bind(ADDR) #将套接字绑定到服务器地址和端口 15 tcpSerSock.listen(1) #开启TCP监听,参数是传入连接在排队的请求的最大数,设置为0和1相同 16 17 while True: 18 print('waiting for connection...') 19 tcpCliSock,addr = tcpSerSock.accept() #生成一个包含socket对象(tcpClisock)和连接的IP地址、端口(addr)的元组 20 print('...connected from:',addr) 21 22 while True: 23 data = (tcpCliSock.recv(BUFSIZ)).decode('utf-8') #接收客户端发来的TCP消息 24 if not data: 25 break 26 27 #发送给客户端的TCP消息,使用utf-8编码转成二进制数据发送,只能转成二进制数据才能发送 28 tcpCliSock.send(bytes(('[%s] %s' % (ctime(),data)),'utf-8')) 29 30 tcpCliSock.close() #关闭当前客户端连接,然后等待另一个客户端连接 31 tcpSerSock.close() #这一行在这个程序里永远不会执行,只是提醒可以使用这个来考虑一个更优雅的退出方式3)创建TCP客户端伪代码
cs = socket() # 创建客户端套接字 cs.connect() # 尝试连接服务器 comm_loop: # 通信循环 cs.send()/cs.recv() # 对话(发送/接收) cs .close() # 关闭客户端套接字4) 创建TCP客户端代码
1 ''' 2 创建TCP客户端 3 ''' 4 5 from socket import * 6 7 HOST = 'localhost' 8 PORT = 21567 #端口号应与服务器设置的完成相同 9 BUFSIZ = 1024 10 ADDR = (HOST,PORT) 11 12 tcpCliSOCK = socket(AF_INET,SOCK_STREAM) 13 tcpCliSOCK.connect(ADDR) #主动调用并连接服务器 14 15 while True: 16 data = input('>') 17 if not data: 18 break 19 20 #发送给服务器的TCP消息,使用utf-8编码转成二进制数据发送,只能转成二进制数据才能发送 21 tcpCliSOCK.send(bytes(data,'utf-8')) 22 data = tcpCliSOCK.recv(BUFSIZ) #接收服务器发来的TCP消息 23 if not data: 24 break 25 print(data.decode('utf-8')) 26 tcpCliSOCK.close()5) 执行TCP服务器和客户端
执行TCP服务器
执行TCP客户端
UDP因为数据报套接字是无连接的,所以就没有为了成功通信而使一个客户端连接到一个独立的套接字“转换”的操作。这些服务器仅仅接受消息并有可能回复数据。
1) 创建UDP服务器的伪代码
ss = socket() # 创建服务器套接字 ss.bind() # 绑定服务器套接字 inf_loop: # 服务器无限循环 cs = ss.recvfrom()/ss.sendto() # 关闭(接收/发送) ss .close() # 关闭服务器套接字2) 创建UDP服务器代码
1 ''' 2 创建UDP服务器 3 ''' 4 5 from socket import * 6 from time import ctime 7 8 HOST = '' #空白表示可以使用任何可用的地址,是对bind()方法的标识 9 PORT = 21567 #端口 10 BUFSIZ = 1024 #缓冲区大小设置为1KB,可根据网络性能和程序需要改变这个容量 11 ADDR = (HOST,PORT) 12 13 udpSerSock = socket(AF_INET,SOCK_DGRAM) #创建套接字 14 udpSerSock.bind(ADDR) #将套接字绑定到服务器地址和端口 15 16 while True: 17 print('waiting for message...') 18 data,addr = udpSerSock.recvfrom(BUFSIZ) #接收客户端发来的UDP消息,此消息包含客户端发来数据和客户端地址、端口号的元组 19 20 #发送给客户端的UDP消息,使用utf-8编码转成二进制数据发送,只能转成二进制数据才能发送 21 udpSerSock.sendto(('[%s] %s' % (ctime(),data.decode('utf-8'))).encode('utf-8'),addr) 22 print('...received from and returned to:',addr) 23 udpSerSock.close() #这一行在这个程序里永远不会执行,只是提醒可以使用这个来考虑一个更优雅的退出方式3) 创建UDP客户端伪代码
cs = socket() # 创建客户端套接字 comm_loop: # 通信循环 cs.sendto()/cs.recvfrom() # 对话(发送/接收) cs .close() # 关闭客户端套接字4) 创建UDP客户端代码
1 ''' 2 创建UDP客户端 3 ''' 4 5 from socket import * 6 7 HOST = b'localhost' 8 PORT = 21567 #端口号应与服务器设置的完成相同 9 BUFSIZ = 1024 10 ADDR = (HOST,PORT) 11 12 udpCliSOCK = socket(AF_INET,SOCK_DGRAM) 13 14 while True: 15 data = input('>') 16 if not data: 17 break 18 19 #发送给服务器的UDP消息,使用utf-8编码转成二进制数据发送,只能转成二进制数据才能发送 20 udpCliSOCK.sendto(data.encode('utf-8'),ADDR) 21 data,ADDR = udpCliSOCK.recvfrom(BUFSIZ) #接收服务器发来的UDP消息 22 if not data: 23 break 24 print(data.decode('utf-8')) 25 udpCliSOCK.close()5) 执行TCP服务器和客户端
执行UDP服务器
执行UDP客户端
socketserver是标准库中的一个高级模块,目标是简化很多样板代码
类
描述
TCPServer/UDPServer
基础的网络同步TCP/UDP 服务器
UnixStreamServer/UnixDatagramServer
基于文件的基础同步TCP/UDP 服务器
ForkingTCPServer/ForkingUDPServer
ForkingMixIn 和TCPServer/UDPServer 的组合
ThreadingTCPServer/ThreadingUDPServer
ThreadingMixIn 和TCPServer/UDPServer 的组合
BaseRequestHandler
包含处理服务请求的核心功能;仅仅用于推导,这样无法创建这个类的实例;
可以使用StreamRequestHandler 或DatagramRequestHandler 创建类的实例
TCP服务器输出
TCP客户端输出
Twisted 是一个完整的事件驱动的网络框架,利用它既能使用也能开发完整的异步网络应用程序和协议,不是Python 标准库的一部分
python3.6版本pip install twisted会报错,在Python扩展包的非官方Windows二进制文件里https://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载Twisted-18.7.0-cp36-cp36m-win_amd64.whl,
pip install Twisted-18.7.0-cp36-cp36m-win_amd64.whl进行安装
执行TCP服务器
执行TCP客户端
模块
描述
socket
是低级网络编程接口
asyncore/asynchat
提供创建网络应用程序的基础设施,并异步地处理客户端
select
在一个单线程的网络服务器应用中管理多个套接字连接
SocketServer
高级模块,提供网络应用程序的服务器类,包括forking 或threading 簇
1) select模块和socket 模块
当开发低级套接字程序时,经常配合使用select 模块和socket 模块。select 模块提供了select()函数,该函数管理套接字对象集合。它所做的最有用的一个事情就是接收一套套接字,并监听它们活动的连接。select()函数将会阻塞。
2) async*和SocketServer 模块
async*和SocketServer 模块都提供更高级的功能。它们以socket 和/或select 模块为基础编写,能够使客户端/服务器系统开发更加迅速,因为它们已经自动处理了所有的底层代码。你需要做的所有工作就是以自己的方式创建或继承适当的基类。
3) Concurrence现代化的网络框架
Concurrence 是一个搭配了libevent 的高性能I/O 系统,libevent 是一个低级事件回调调度系统。Concurrence 是一个异步模型,它使用轻量级线程(执行回调)以事件驱动的方式进行线程间通信和消息传递工作。
现代网络框架遵循众多异步模型(greenlet、generator 等)之一来提供高性能异步服务器
转载于:https://www.cnblogs.com/longBlogs/p/9761836.html