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 地址和端口号,再指定协议类型即可. ...
随机推荐
- 使用Redis实现延时任务(一)
使用Redis实现延时任务(一) 前提 最近在生产环境刚好遇到了延时任务的场景,调研了一下目前主流的方案,分析了一下优劣并且敲定了最终的方案.这篇文章记录了调研的过程,以及初步方案的实现. 候选方案对 ...
- Spring与Redis整合(spring-data-redis)
maven依赖 <properties> <!-- redis 版本 --> <redis.version>2.9.0</redis.version> ...
- 12、pytest -- 缓存:记录执行的状态
目录 1. cacheprovider插件 1.1. --lf, --last-failed:只执行上一轮失败的用例 1.2. --ff, --failed-first:先执行上一轮失败的用例,再执行 ...
- 一文彻底搞懂CAS实现原理 & 深入到CPU指令
本文导读: 前言 如何保障线程安全 CAS原理剖析 CPU如何保证原子操作 解密CAS底层指令 小结 朋友,文章优先发布公众号,如果你愿意,可否扫文末二维码关注下? 前言 日常编码过程中,基本不会直接 ...
- 影响ES相关度算分的因素
相关性算分 指文档与查询语句间的相关度,通过倒排索引可以获取与查询语句相匹配的文档列表 如何将最符合用户查询需求的文档放到前列呢? 本质问题是一个排序的问题,排序的依据是相关性算分,确定倒排索引哪 ...
- Debug 利器:pstack & strace
工作中难免会遇到各种各样的 bug,对于开发环境 or 测试环境的问题还好解决,可以使用 gdb 打断点或者在代码中埋点来定位异常; 但是遇到线上的 bug 就很难受了,由于生产环境不能随意替换.中断 ...
- [ch04-03] 用神经网络解决线性回归问题
系列博客,原文在笔者所维护的github上:https://aka.ms/beginnerAI, 点击star加星不要吝啬,星越多笔者越努力. 4.3 神经网络法 在梯度下降法中,我们简单讲述了一下神 ...
- 构建一个flink程序,从kafka读取然后写入MYSQL
最近flink已经变得比较流行了,所以大家要了解flink并且使用flink.现在最流行的实时计算应该就是flink了,它具有了流计算和批处理功能.它可以处理有界数据和无界数据,也就是可以处理永远生产 ...
- 2019-2020-1 20199304《Linux内核原理与分析》第一周作业
通过对Linux基础课程的学习,我对Linux的背景以及和Windows的区别有了了解, Linux 平台:大都为开源自由软件,用户可以修改定制和再发布,由于基本免费没有资金支持,部分软件质量和体验欠 ...
- 【立即报名】解码AI大杀器:华为云GPU+Tensorflow 容器实战
导语: 人工智能的火热,带来了一波学习TensorFlow深度学习框架的热潮.聊深度学习免不了要用GPU,但目前GPU费用较高,对于个人学习者和创业公司来讲的话,按需配置的云GPU服务器是一个不错的选 ...