python网络编程socket编程(TCP、UDP客户端服务器)
摘录 python核心编程
使用socket()模块函数创建套接字——通信端点
>>> from socket import *
>>> tcpSock = socket(AF_INET,SOCK_STREAM)
>>> udpSock = socket(AF_INET,SOCK_DGRAM)
其中,AF_INET表示使用的是IPv4协议,SOCK_STREAM表示的面向连接的TCP协议,SOCK_DGRAM表示面向无连接的UDP协议。
在创建TCP和UDP客户端与服务器前,先看看socket模块的属性以及套接字对象的方法
socket模块的属性:
属性名 | 描述 |
数据属性 | |
AF_UNIX、AF_INET、AF_INET6、AF_NETLINK、AF_TIPC | python支持的套接字地址家族 |
SO_STREAM、SO_DGRAM | 套接字类型(TCP=流,UDP=数据报) |
has_ipv6 | 表示是否支持IPv6的布尔标志 |
异常 | |
error | 套接字相关错误 |
herror | 主机和地址相关错误 |
gaierror | 地址相关错误 |
timeout | 超时时间 |
函数 | |
socket() | 以给定的地址家族、套接字类型和协议类型(可选)创建一个套接字对象 |
socketpair() | 以给定的地址家族、套接字类型和协议类型(可选)创建一对套接字对象 |
create_connection() | 常规函数,它接收一个地址(主机、端口号)对,返回套接字对象 |
fromfd() | 以一个打开的文件描述符创建一个套接字对象 |
ssl() | 通过套接字启动一个安全套接字连接,不执行证书验证 |
getaddrinfo() | 获取一个五元组序列形式的地址信息 |
getnameinfo() | 给定一个套接字地址,返回二元组(主机名、端口号) |
getfqdn() | 返回完整的域名 |
gethostname() | 返回当前主机名 |
gethostbyname() | 将一个主机名映射到它的IP地址 |
gethostbyname_ex() | gethostname()的扩展,返回主机名、别名主机集合和IP地址列表 |
gethostbyaddr() | 将一个IP地址映射到DNS信息;返回和gethostbyname_ex()相同的三元组 |
getprotobyname() | 将一个协议名映射到一个数字 |
getservbyname()/getservbyport() | 将一个服务名映射到一个端口号,或者反过来;任何一个函数,协议名都是可选的 |
ntohl()/ntohs() | 将来自网络的整数转换为主机字节顺序 |
htonl()/htons() | 将来自主机的整数转换为网络字节顺序 |
inet_aton()/inet_ntoa() | 将IP地址八进制字符串转换为32位包格式,或者反过来(仅用于IPv4地址) |
inet_pton()/inet_ntop() | 将IP地址字符串转换为打包的二进制格式,或者反过来(适用于IPv4和IPv6) |
getdefaulttimeout()/setdefaulttimeout() | 以秒为单位,获得/设置默认套接字超时时间 |
套接字对象方法和属性:
名称 | 描述 |
服务器套接字特有方法 | |
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 | 套接字协议 |
创建TCP服务器
首先先来说说服务器设计的一般思路(伪代码):
ss = socket() #1、创建服务器套接字
ss.bind() #2、套接字于地址绑定
ss.listen() #3、监听连接
inf_loop: #4、服务器无限循环:
cs = ss.accept() #1)接收客户端连接
comm_loop: #2)通信循环
cs.recv()/cs.send() #①对话(接收/发送)
cs.close() #3)关闭客户端套接字
ss.close() #5、关闭服务器套接字(如有必要)
值得关心的是accept()的调用。该步骤默认会以阻塞的形式开启一个单线程服务器,用于等待客户端的连接,如果连接成功,则会返回一个独立的客户端套接字,用于和即将到来的消息进行交换,直到连接终止(终止方式一般是一方关闭连接或者向另外发送一个空字符串)。
下面的tsTserv.py脚本描述的是一个TCP服务器,接收来自客户端的消息,然后将消息加上时间戳前缀并发送给客户端:
#导入了time.time()和socket模块的所有属性
from socket import *
from time import ctime HOST = '' #空白的变量,表示可以使用任何可用的地址
PORT = 21567 #端口号
BUFSIZ = 1024 #缓冲区大小,单位是bite
ADDR = (HOST,PORT) tcpSerSock = socket(AF_INET,SOCK_STREAM) #创建一个TCP套接字
tcpSerSock.bind(ADDR) #绑定地址
tcpSerSock.listen(5) #启动TCP监听,其中5表示在连接被转接或拒绝之前,传入连接请求的最大数 while True: #服务器无限循环
print('服务器等待连接……')
tcpCliSock,addr = tcpSerSock.accept() #被动等待客户端的连接,当连接请求出现的时候,会返回一个新的套接字和客户端的地址组成的元组,于该客户端的通信是在这个新的套接字上进行数据的接受和发送s
print('……来自于:',addr) while True: #上述新套接字中进行通信循环
data = tcpCliSock.recv(BUFSIZ).decode('utf-8') #接受客户端发送过来的消息,从网络传输过来的是bytes类型的,需要解码
print(data)
if not data: #如果客户端发送的内容为空,认为客户端已经关闭,此时应该退出通信循环
break
tcpCliSock.send(('[%s] %s' % (ctime(),data)).encode('utf-8')) #服务器将处理的内容发送给客户端,需要将字符串类型数据转化为bytes数据。 tcpCliSock.close() #关闭当前客户端连接,下一步是等待另外一个客户端
tcpSerSock.close()
创建TCP客户端
下面给出创建客户端的伪代码:
cs = socket() #创建客户端套接字
cs.connect() #尝试连接服务器
comm_loop: #通信循环
cs.send()/cs.recv() #对话(发送/接收)
cs.close() #关闭客户端套接字
下面的tsTclnt.py脚本是和上面创建的服务器相关的客户端代码-连接服务器,并以逐行数据的形式提示用户,并展示从服务器返回的数据:
#导入socket模块的所有属性
from socket import * HOST = '192.168.1.125' #服务器的主机名,这里是在本地一台计算机上测试,所以这里是本地计算地址
PORT = 21567 #服务器的端口号,必须和服务端的端口号设置一样
BUFSIZ = 1024
ADDR = (HOST,PORT) tcpCliSock = socket(AF_INET,SOCK_STREAM) #创建客户端套接字
tcpCliSock.connect(ADDR) #主动调用并尝试连接服务器 while True: #无限循环
data = input('>') #等待客户端的录入
if not data: #如果用户没有输入任何的东西,则退出无限循环
break
tcpCliSock.send(data.encode('utf-8')) #将客户端的数据发送到服务器,并将字符串编码为bytes类型
data = tcpCliSock.recv(BUFSIZ).decode('utf-8') #接收服务器返回的数据
if not data: #如果服务器终止了或者上一步的recv()方法调用失败的话,也会退出无限循环
break
print(data) #正常情况下,从服务器返回的数据会被打印出来 tcpCliSock.close() #关闭客户端套接字
运行结果
首先,启动服务器
然后,在另外一台计算机(或者本机,记得更改对应的IP地址呦)上执行客户端脚本。然后就可以进行两台计算机的通信表演了。
这里要特别强调的是,我测试的版本是3.6x,通信端点发送接收内容的一定要进行编码和解码!因为,区别于2.x版本,在python3.x版本中,字符串和bytes是两种不同的数据类型了。
创建UDP服务器
和TCP服务器相比,UDP不需要那么多设置(因为他不是面向连接的),下面是伪代码:
ss = socket() #创建服务器套接字
ss.bind() #绑定服务器套接字
inf_loop: #服务器无限循环
cs = ss.recvfrom()/ss.sendto() #关闭(接收/发送)
ss.close() #关闭服务器套接字
上脚本:
#导入需要的模块
from socket import *
from time import ctime HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT) udpSerSock = socket(AF_INET,SOCK_DGRAM)
udpSerSock.bind(ADDR) #这里明显和TCP不同,没有所谓的‘监听传入的连接’的动作 while True:
print('等待接收消息……')
data,addr = udpSerSock.recvfrom(BUFSIZ) #接收数据报
udpSerSock.sendto(('时间:%s 地址:%s 内容:%s' % (ctime(),addr,data)).encode('utf-8'),addr) #给客户端返回数据
print('……接收并返回数据于:',addr) #服务器上打印记录信息 udpSerSock.close() #一般来说用不到,更优雅的方法是将无限循环放入一个try catch模块中,在捕捉异常或者finally中实现关闭套接字
创建UDP客户端
from socket import * HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT) udpCliSOcket = socket(AF_INET,SOCK_DGRAM) while True:
data = input('请输入:')
if not data:
break
udpCliSOcket.sendto(data.encode('utf-8'),ADDR)
data,ADDR = udpCliSOcket.recvfrom(BUFSIZ)
if not data:
break
print(data.decode('utf-8'),ADDR) udpCliSOcket.close()
看到:UDP和TCP客户端循环的方式基本一样,唯一的区别在于,事先不需要建立与UDP服务器的连接,只是简单的发送一条消息并等待服务器的回复。
python网络编程socket编程(TCP、UDP客户端服务器)的更多相关文章
- 网络编程—网络基础概览、socket,TCP/UDP协议
网络基础概览 socket概览 socket模块—TCP/UDP的实现 TCP/UDP总结 网络基础概览 osi七层协议各层主要的协议 # 物理层传输电信号1010101010 # 数据链路层,以太网 ...
- java网络编程socket\server\TCP笔记(转)
java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04| 分类: Socket | 标签:java |举报|字号 订阅 1 TCP的开销 a ...
- 网络编程Socket之TCP之close/shutdown具体解释(续)
接着上一篇网络编程Socket之TCP之close/shutdown具体解释 如今我们看看对于不同情况的close的返回情况和可能遇到的一些问题: 1.默认操作的close 说明:我们已经知道writ ...
- python基础之socket编程 (转自林海峰老师)
python基础之socket编程 阅读目录 一 客户端/服务器架构 二 osi七层 三 socket层 四 socket是什么 五 套接字发展史及分类 六 套接字工作流程 七 基于TCP的套接字 ...
- Python 基础之socket编程(一)
Python 基础之socket编程(一) 可以进行通信玩儿了,感觉不错不错,网络通信就像打电话,我说一句你听一句之后,你再说一句,我听一句,就这样.....下去了.不扯淡了,来来来,看看今天都搞了点 ...
- Python 基础之socket编程(二)
Python 基础之socket编程(二) 昨天只是对socket编程做了简单的介绍,只是把socket通信的框架搭建起来,要对其中的功能进行进一步的扩充,就来看看今天的料哈! 一.基于tcp的套接字 ...
- Python开发——12.socket编程
一.OSI七层 1.物理层 物理层的主要功能是基于电气特性发送高低电压(高代表1,低代表0)形成电信号,使计算机完成组网以达到接入Internet的目的 2.数据链路层 数据链路层是用来定义电信号的分 ...
- Python 基础之socket编程(三)
python 基础之socket编程(三) 前面实现的基于socket通信只能实现什么呢?在tcp协议的通信中就是一个用户说一句,服务端给你回一句,你再给服务端说一句,服务端再给你回一句,就这样一直友 ...
- python网络编程(Socket、TCP、UDP)
Socket 是网络编程的一个抽象概念,通常我们用一个Socket表示 "打开了一个网络链接",而打开一个Socket 需要知道目标计算机的IP 地址和端口号,再指定协议类型即可. ...
随机推荐
- (一)OpenStack---M版---双节点搭建---基础环境配置
↓↓↓↓↓↓↓↓视频已上线B站↓↓↓↓↓↓↓↓ >>>>>>传送门 配置如下 本次搭建采用2台4核4G的虚拟机,也可以用2台2核4G 主机名 配置 网络 Contr ...
- Mysql查询语句之排序查询
语法: /* select 查询列表 from 表 [where 筛选条件] order by 排序列表 [asc/desc] */ ①asc为升序,desc为降序,且默认为升序 ②order by子 ...
- Redis开发与运维:SDS与embstr、raw 深入理解
对于上一篇文章,我又自己总结归纳并补充了一下,有了第二篇. 概览 <<左移 开始之前,我们先准备点东西:位运算 i<<n 总结为 i*2^n 所以 1<<5 = 2 ...
- selenium(java)浏览器多窗口切换处理
要在多个窗口直接切换,首先获取每个窗口的唯一标示符(句柄),通过窗口属性可以获取所有打开窗口的标示符,以集合的形式返回:以下示例: Set<String> winHandels ...
- Linux01机和Linux02机的切换 和秘钥的配置
先试一下 01机和02机是否可以切换成功 使用 ssh root@ip地址 输入密码 ifconfig查看ip是否正确 切换回01机 01机配置的秘钥 查看隐形文件 01机配置秘钥 输入 ssh-c ...
- yarn和npm的对比以及yarn的使用
0--前言 为什么要使用yarn,如果你从事前端开发有些年头了,那你肯定对npm又爱又恨,爱就不说了,恨嘛,就是NPM经常奇慢和卡顿,这还能忍,经常各种错误就没法忍了,尤其是他人创建的项目,自己在安装 ...
- kubectl exec 在kubelet中的处理流程
基于kuebrnetes v1.17 简单来说,一个完整的streaming请求如下: 客户端 kubectl exec -i -t ... kube-apiserver 向 Kubelet 发送流式 ...
- C#程序编写高质量代码改善的157个建议[正确操作字符串、使用默认转型方法、却别对待强制转换与as和is]
前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理解的东西,有些地方可能理解的不太到位,还望指正. 建议1. ...
- 图解leetcode —— 124. 二叉树中的最大路径和
前言: 每道题附带动态示意图,提供java.python两种语言答案,力求提供leetcode最优解. 描述: 给定一个非空二叉树,返回其最大路径和. 本题中,路径被定义为一条从树中任意节点出发,达到 ...
- layui中formSelects的使用
1.下载 下载地址:https://github.com/hnzzmsf/layui-formSelects 2. 引入 //引入formSelects.css <link rel=" ...