基于python的网络编程
来源:互联网 发布:闪电站小猪知乎 编辑:程序博客网 时间:2024/05/16 12:52
建议关注:TCP和UDP的区别、socket其中的参数含义、TCP三次握手及传递的参数、可以写出socket通讯伪代码。
网络编程就是如何在程序中实现两台计算机的通信。更确切地说,网络通信是两台计算机上的两个进程之间的通信。比如,浏览器进程和新浪服务器上的某个Web服务进程在通信,而QQ进程是和腾讯的某个服务器上的某个进程在通信。网络编程对所有开发语言都是一样的,Python也不例外。用Python进行网络编程,就是在Python程序本身这个进程内,连接别的服务器进程的通信端口进行通信。
一、###########硬件客户端/服务器架构和 软件客户端/服务器架构
硬件的客户端/服务器架构,例如打印服务器、文件服务器(客户可以远程把服务器的磁盘映射到自己本体并使用);软件客户端/服务器架构主要是程序的运行、数据收发、升级等,最常见的是Web服务器、数据库服务器。如一台机器存放一些网页或Web应用程序,然后启动服务。其服务器的任务就是接受客户端的请求,把网页发给客户端(如用户计算机上的浏览器),然后再等待下一个客户端请求。软件服务器也运行在一块硬件之上,但是没有像硬件服务器那样的专用外围设备(如打印机、磁盘驱动器等)
二、######## 硬件客户端/服务器架构和软件客户端/服务器架构
硬件的客户端/服务器架构,例如打印服务器、文件服务器(客户可以远程把服务器的磁盘映射到自己本体并使用);软件客户端/服务器架构主要是程序的运行、数据收发、升级等,最常见的是Web服务器、数据库服务器。如一台机器存放一些网页或Web应用程序,然后启动服务。其服务器的任务就是接受客户端的请求,把网页发给客户端(如用户计算机上的浏览器),然后再等待下一个客户端请求。
三、################ 套接字Socket
1.什么是套接字
套接字是一种具有之前所说的“通信端点”概念的计算网络数据结构。相当于电话插口,没它无法通信,这个比喻非常形象。
套接字起源于20世纪70年代加州伯克利分校版本的Unix,即BSD Unix。又称为“伯克利套接字”或“BSD套接字”。最初套接字被设计用在同一台主机上多个应用程序之间的通讯,这被称为进程间通讯或IPC。
套接字分两种:基于文件型和基于网络的
第一个套接字家族为AF_UNIX,表示“地址家族:UNIX”。包括Python在内的大多数流行平台上都使用术语“地址家族”及其缩写AF。由于两个进程都运行在同一台机器上,而且这些套接字是基于文件的,所以它们的底层结构是由文件系统来支持的。可以理解为同一台电脑上,文件系统确实是不同的进程都能进行访问的。
第二个套接字家族为AF_INET,表示”地址家族:Internet“。还有一种地址家族AF_INET6被用于网际协议IPv6寻址。python 2.5中加入了一种Linux套接字的支持:AF_NETLINK(无连接)套接字家族,让用户代码与内核代码之间的IPC可以使用标准BSD套接字接口,这种方法更为精巧和安全。
Python只支持AF_UNIX、AF_NETLINK和AF_INET家族。网络编程关注AF_INET。
如果把套接字比作电话的查看——即通信的最底层结构,那主机与端口就相当于区号和电话号码的一对组合。一个因特网地址由网络通信必须的主机与端口组成。
而且另一端一定要有人接听才行,否则会提示”对不起,您拨打的电话是空号,请查询后再拨“。同样你也可能会遇到如”不能连接该服务器、服务器无法响应“等。合法的端口范围是0~65535,其中小于1024端口号为系统保留端口。
知名端口号列表: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
2.面向连接与无连接
面向连接:通信之前一定要建立一条连接,这种通信方式也被成为”虚电路“或”流套接字“。面向连接的通信方式提供了顺序的、可靠地、不会重复的数据传输,而且也不会被加上数据边界。这意味着,每发送一份信息,可能会被拆分成多份,每份都会不多不少地正确到达目的地,然后重新按顺序拼装起来,传给正等待的应用程序。
实现这种连接的主要协议就是传输控制协议TCP。要创建TCP套接字就得创建时指定套接字类型为SOCK_STREAM。TCP套接字这个类型表示它作为流套接字的特点。由于这些套接字使用网际协议IP来查找网络中的主机,所以这样形成的整个系统,一般会由这两个协议(TCP和IP)组合描述,即TCP/IP。
无连接:无需建立连接就可以通讯。但此时,数据到达的顺序、可靠性及不重复性就无法保障了。数据报会保留数据边界,这就表示数据是整个发送的,不会像面向连接的协议先拆分成小块。它就相当于邮政服务一样,邮件和包裹不一定按照发送顺序达到,有的甚至可能根本到达不到。而且网络中的报文可能会重复发送。
那么这么多缺点,为什么还要使用它呢?由于面向连接套接字要提供一些保证,需要维护虚电路连接,这都是严重的额外负担。数据报没有这些负担,所有它会更”便宜“,通常能提供更好的性能,更适合某些场合,如现场直播要求的实时数据讲究快等。
实现这种连接的主要协议是用户数据报协议UDP。要创建UDP套接字就得创建时指定套接字类型为SOCK_DGRAM。这个名字源于datagram(数据报),这些套接字使用网际协议来查找网络主机,整个系统叫UDP/IP。
四、python 中的网络编程
1、socket()模块函数
使用socket模块的socket()函数来创建套接字。语法如下:
socket(socket_family, socket_type, protocol=0)
其中socket_family不是AF_VNIX就是AF_INET,socket_type可以是SOCK_STREAM或者SOCK_DGRAM,protocol一般不填,默认值是0。
创建一个TCP/IP套接字的语法如下:
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
同样创建一个UDP/IP套接字的语法如下:
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
由于socket模块中有太多属性,所以使用"from socket import *"语句,把socket模块里面的所有属性都带到命名空间中,较"from module import *"语句大幅缩短代码。调用如下:
tcpSock = socket(AF_INET, SOCK_STREAM)
2、 套接字对象方法 下面是最常用的套接字对象方法:
服务器端套接字函数
公共用途的套接字函数 面向模块的套接字函数
面向文件的套接字函数
s.family 套接字家族 s.type :套接字类型 s.proto :套接字协议
###################################实例##############################################
1、创建TCP服务器
核心操作如下:
ss = socket() # 创建服务器套接字
ss.bind() # 地址绑定到套接字上
ss.listen() # 监听连接
inf_loop: # 服务器无限循环
cs = ss.accept() # 接受客户端连接 阻塞式:程序连接之前处于挂起状态
comm_loop: # 通信循环
cs.recv()/cs.send() # 对话 接受与发送数据
cs.close() # 关闭客户端套接字
ss.close() # 关闭服务器套接字 (可选)
#############TCP时间服务器 tcpSerSock.py(接受客户端数据,打上时间戳返回)配置代码如下###############
- # -*- coding: utf-8 -*-
- from socket import *
- from time import ctime
- HOST = 'localhost' #主机名
- PORT = 21567 #端口号
- BUFSIZE = 1024 #缓冲区大小1K
- ADDR = (HOST,PORT)
- tcpSerSock = socket(AF_INET, SOCK_STREAM)
- tcpSerSock.bind(ADDR) #绑定地址到套接字
- tcpSerSock.listen(5) #监听 最多同时5个连接进来
- while True: #无限循环等待连接到来
- try:
- print 'Waiting for connection ....'
- tcpCliSock, addr = tcpSerSock.accept() #被动接受客户端连接
- print u'Connected client from : ', addr
- while True:
- data = tcpCliSock.recv(BUFSIZE) #接受数据
- if not data:
- break
- else:
- print 'Client: ',data
- tcpCliSock.send('[%s] %s' %(ctime(),data)) #时间戳
- except Exception,e:
- print 'Error: ',e
- tcpSerSock.close() #关闭服务器
把HTTP头和网页分离一下,把HTTP头打印出来,网页内容保存到文件代码示例:
header, html = data.split('\r\n\r\n', 1)print header# 把接收的数据写入文件:with open('sina.html', 'wb') as f: f.write(html)
# 创建新线程来处理TCP连接: t = threading.Thread(target=tcplink, args=(sock, addr)) t.start()
每个连接都必须创建新线程(或进程)来处理,否则,单线程在处理连接的过程中,无法接受其他客户端的连接:
2、创建TCP服务器
核心操作如下:
cs = socket() # 创建客户端套接字
cs.connect() # 尝试连接服务器
comm_loop: # 通讯循环
cs.send()/cs.recv() # 对话 发送接受数据
cs.close() # 关闭客户端套接字
###########TCP时间戳客户端 tsTclnt.py(发送客户端数据,接受时间戳返回)配置代码如下##########
- # -*- coding: utf-8 -*-
- from socket import *
- HOST = 'localhost' #主机名
- PORT = 21567 #端口号 与服务器一致
- BUFSIZE = 1024 #缓冲区大小1K
- ADDR = (HOST,PORT)
- tcpCliSock = socket(AF_INET, SOCK_STREAM)
- tcpCliSock.connect(ADDR) #连接服务器
- while True: #无限循环等待连接到来
- try:
- data = raw_input('>')
- if not data:
- break
- tcpCliSock.send(data) #发送数据
- data = tcpCliSock.recv(BUFSIZE) #接受数据
- if not data:
- break
- print 'Server: ', data
- except Exception,e:
- print 'Error: ',e
- tcpCliSock.close() #关闭客户端
建议:创建线程来处理客户端请求。SocketServer模块是一个基于socket模块的高级别的套接字通信模块,支持新的线程或进程中处理客户端请求。同时建议在退出和调用服务器close()函数时使用try-except语句。
3、创建UDP服务器
服务器 udpSerSock.py
核心操作如下:
ss = socket() # 创建服务器套接字
ss.bind() # 绑定服务器套接字
inf_loop: # 服务器无限循环
cs = ss.recvfrom()/ss.sendto()
# 对话 接受与发送数据
ss.close() # 关闭服务器套接字
- # -*- coding: utf-8 -*-
- from socket import *
- from time import ctime
- HOST = '' #主机名
- PORT = 21567 #端口号
- BUFSIZE = 1024 #缓冲区大小1K
- ADDR = (HOST,PORT)
- udpSerSock = socket(AF_INET, SOCK_DGRAM)
- udpSerSock.bind(ADDR) #绑定地址到套接字
- while True: #无限循环等待连接到来
- try:
- print 'Waiting for message ....'
- data, addr = udpSerSock.recvfrom(BUFSIZE) #接受UDP
- print 'Get client msg is: ', data
- udpSerSock.sendto('[%s] %s' %(ctime(),data), addr) #发送UDP
- print 'Received from and returned to: ',addr
- except Exception,e:
- print 'Error: ',e
- udpSerSock.close() #关闭服务器
客户端 udpCliSock.py
核心操作如下:
cs = socket() # 创建客户端套接字
inf_loop: # 服务器无限循环
cs.sendto()/cs.recvfrom() # 对话 接受与发送数据
cs.close() # 关闭客户端套接字
- # -*- coding: utf-8 -*-
- from socket import *
- HOST = 'localhost' #主机名
- PORT = 21567 #端口号 与服务器一致
- BUFSIZE = 1024 #缓冲区大小1K
- ADDR = (HOST,PORT)
- udpCliSock = socket(AF_INET, SOCK_DGRAM)
- while True: #无限循环等待连接到来
- try:
- data = raw_input('>')
- if not data:
- break
- udpCliSock.sendto(data, ADDR) #发送数据
- data,ADDR = udpCliSock.recvfrom(BUFSIZE) #接受数据
- if not data:
- break
- print 'Server : ', data
- except Exception,e:
- print 'Error: ',e
- udpCliSock.close() #关闭客户端
##################Socket模块属性#######################
除了我们已经很熟悉的socket.socket()函数之外,socket模块还有很多属性可供网络应用程序使用。
表 Socket模块属性
属 性 名 字
描 述
数据属性
AF_UNIX, AF_INET, AF_INET6a
Python支持的套接字地址家族
SO_STREAM, SO_DGRAM
套接字类型(TCP = 流,UDP = 数据报)
has_ipv6b
表示是否支持IPv6的布尔型标志
异常
error
套接字相关错误
herrora
主机和地址相关的错误
gaierrora
地址相关的错误
timeoutb
超时
函数
socket()
用指定的地址家族、套接字类型和协议类型创建一个套接字对象(可选)
socketpair()c
用指定的地址家族、套接字类型和协议类型创建一对套接字对象(可选)
fromfd()
用一个已经打开的文件描述符创建一个套接字对象
ssl()d
在套接字上发起一个安全套接字层(SSL)。不做证书验证
getaddrinfo()a
得到地址信息
getfqdn()e
返回完整的域的名字
gethostname()
得到当前主机名
gethostbyname()
由主机名得到对应的IP地址
gethostbyname_ex()
gethostbyname()的扩展版本,返回主机名、主机所有的别名和IP地址列表
gethostbyaddr()
由IP地址得到DNS信息,返回一个类似gethostbyname_ex()的3元组
getprotobyname()
由协议名(如'tcp')得到对应的号码
getservbyname()/getservbyport()
由服务名得到对应的端口号或反之;两个函数中,协议名都是可选的
ntohl()/ntohs()
把一个整型由网络字节序转换为主机字节序
htonl()/htons()
把一个整型由主机字节序转换为网络字节序
inet_aton()/inet_ntoa()
把IP地址转为32位整型,或反之(仅对IPv4地址有效)
inet_pton()/inet_ntop()b
把IP地址转为二进制格式或反之(对IPv4和Ipv6地址都有效)
getdefaulttimeout()/setdefaulttimeout()b
得到/设置默认的套接字超时时间,单位秒(浮点型)
- 基于python的网络编程
- Python网络编程01-----基于TCP的Python简易服务器
- Python网络编程02----基于UDP的Python简易服务器
- [Python] Twiested - 基于事件驱动的网络编程
- Python的网络编程
- Python的网络编程
- Python的网络编程
- 基于TCP的网络编程
- 基于UDP的网络编程
- 基于TCP的网络编程
- 基于UDP的网络编程
- 基于Linux的网络编程
- 基于网络编程的文件传输
- 网络编程:基于TCP的socket网络传输视频(C++, python)
- 网络编程----基于TCP的socket编程
- 基于Python的socket编程
- Python的网络编程(一)
- Python的网络编程(二)
- 线程状态,多线程的使用,线程的通信(总结)
- HTTP状态码
- javaScript内置对象String
- SSL2681 2017年8月11日提高组T3 难题(math)
- 快速排序
- 基于python的网络编程
- SpringCloud(六):Ribbon示例
- 欢迎来到我的博客
- [转}浅谈协方差矩阵
- 锋利的jQuery中值得记下的例子(1)
- java常用英文单词
- Android初级开发(四)——补充9、GridView(表格)控件的使用
- Python中isinstance用法
- Linux进程入门学习(二)-基础知识