背景

Python 提供了两个级别访问的网络服务:
● 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统 Socket 接口的全部方法。
● 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

socket编程思路

  • 服务端:
  1. 创建套接字,绑定套接字到本地ip和端口:s = socket.socket(socket.AF_INET,socket.SOCK_STREAM), s.bing()
  2. 开始监听连接:s.listen()
  3. 进入循环,不断接受客户端的连接请求: s.accept()
  4. 接受传来的数据,或者发送数据给对方:s.recv(), s.sendall()
  5. 传输完毕后,关闭套接字:s.close()
  • 客户端:
  1. 创建套接字,连接到服务端:s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  2. 发送请求到服务端,并且接受对方的数据:s.sendall(), s.recv()
  3. 传输完毕后,关闭套接字:s.close()
  • 原理图:
    image

  • 参数说明:

s = socket.socket([family[, type[, proto]]])
#参数说明:
#family: 套接字家族,可以使AF_UNIX或者AF_INET。
#type: 套接字类型,根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM,也就是TCP和UDP的#区别。
#protocol: 一般不填默认为0。
#直接socket.socket(),则全部使用默认值创建tcp套接字。

下面是具体的参数定义:

socket类型 描述
socket.AF_UNIX 只能够用于单一的Unix系统进程间通信
socket.AF_INET IPv4
socket.AF_INET6 IPv6
socket.SOCK_STREAM 流式socket , for TCP
socket.SOCK_DGRAM 数据报式socket , for UDP
socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_SEQPACKET 可靠的连续数据包服务
创建TCP Socket: s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
创建UDP Socket: s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

socket套接字方法:

方法 描述
服务器端方法
s.bind() 绑定地址(host,port)到套接字,在AF_INET下,以元组(host,port)的形式表示地址。
s.listen(backlog) 开始监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
s.accept() 被动接受客户端连接,(阻塞式)等待连接的到来,并返回(conn,address)二元元组,其中conn是一个通信对象,可以用来接收和发送数据。address是连接客户端的地址。
客户端方法
s.connect(address) 客户端向服务端发起连接。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
公共方法
s.recv(bufsize) 接收数据,数据以bytes类型返回,bufsize指定要接收的最大数据量。
s.send() 发送数据。返回值是要发送的字节数量。
s.sendall() 完整发送数据。将数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
s.recvform() 接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收的数据,address是发送数据的套接字地址。
s.sendto(data,address) 发送UDP数据,将数据data发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。
s.close() 关闭套接字,必须执行。
s.getpeername() 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
s.getsockname() 返回套接字自己的地址。通常是一个元组(ipaddr,port)
s.setsockopt(level,optname,value) 设置给定套接字选项的值。
s.getsockopt(level,optname[.buflen]) 返回套接字选项的值。
s.settimeout(timeout) 设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())
s.gettimeout() 返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。
s.fileno() 返回套接字的文件描述符。
s.setblocking(flag) 如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。
s.makefile() 创建一个与该套接字相关连的文件
  • 注意事项:
  1. Python3以后,socket传递的都是bytes类型的数据,字符串需要先转换一下,string.encode()编码即可;另一端接收到的bytes数据想转换成字符串,只要bytes.decode()解码一下就可以。
  2. 在正常通信时,accept()和recv()方法都是阻塞的。所谓的阻塞,指的是程序会暂停在那,一直等到有数据过来。

TCP实战

#服务端
import socket
def socket_server(ip_port):
s = socket.socket()
s.bind(ip_port)
s.listen()
conn,address = s.accept()
print('正在监听--->')
while 1:
client_data = conn.recv(1024).decode()
print('收到%s的数据:%s'%(address,client_data))
if client_data == 'exit':
print('通信结束')
break
conn.send('服务器已经收到你的信息'.encode())
s.close()
if __name__ == "__main__":
ip_port = ('127.0.0.1',9999)
socket_server(ip_port)
#客户端
import socket
def socket_client(ip_port):
s = socket.socket()
s.settimeout(5)
s.connect(ip_port)
while 1:
inp = input('请输入发送的数据:').strip()
if not inp:
print('请重新输入')
continue
s.sendall(inp.encode())
if inp == 'exit':
print('关闭连接')
break
re = s.recv(1024).decode()
print(re)
s.close()
if __name__ == '__main__':
ip_port = ('127.0.0.1', 9999)
socket_client(ip_port)

启动实例
image

上面的实例虽然实现了通信,但是如果有多个客户端想要接入进来通信,服务端只监听了一个端口,所以没办法同时和多个通信,想实现多个同时通信需要使用多线程。我们只需要增加服务端的多线程能力即可。

#服务端
import socket
import threading # 导入线程模块
def link_handler(link, client):
"""
该函数为线程需要执行的函数,负责具体的服务器和客户端之间的通信工作
:param link: 当前线程处理的连接
:param client: 客户端ip和端口信息,一个二元元组
:return: None
"""
print("服务器开始接收来自[%s:%s]的请求...." % (client[0], client[1]))
while True: # 利用一个死循环,保持和客户端的通信状态
client_data = link.recv(1024).decode()
if client_data == "exit":
print("结束与[%s:%s]的通信..." % (client[0], client[1]))
break
print("来自[%s:%s]的客户端向你发来信息:%s" % (client[0], client[1], client_data))
link.sendall('服务器已经收到你的信息'.encode())
link.close()
ip_port = ('127.0.0.1', 9999)
sk = socket.socket() # 创建套接字
sk.bind(ip_port) # 绑定服务地址
sk.listen(5) # 监听连接请求
print('启动socket服务,等待客户端连接...')
while True: # 一个死循环,不断的接受客户端发来的连接请求
conn, address = sk.accept() # 等待连接,此处自动阻塞
# 每当有新的连接过来,自动创建一个新的线程,
# 并将连接对象和访问者的ip信息作为参数传递给线程的执行函数
t = threading.Thread(target=link_handler, args=(conn, address))
t.start()

3个客户端依然可以正常通信。
image

UDP实战

相对TCP编程,UDP编程就简单多了,当然可靠性和安全性也差很多。由于UDP没有握手和挥手的过程,因此accept()和connect()方法都不需要。

#服务端
import socket
def socket_server(ip_port):
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(ip_port)
print('正在监听--->')
while 1:
client_data,adderss = s.recvfrom(1024)
print('收到%s客户端数据:%s'%(adderss,client_data.decode()))
if client_data.decode() == 'exit':
print('通信结束')
break
client_data = client_data.decode()
s.sendto(client_data.encode(), adderss)
print('返回数据%s到%s客户端:'%(client_data ,adderss))
s.close()
if __name__ == "__main__":
ip_port = ('127.0.0.1',9999)
socket_server(ip_port)
#客户端
import socket
def socket_client(ip_port):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while 1:
inp = input('请输入发送的数据:').strip()
if not inp:
print('请重新输入')
continue
s.sendto(inp.encode(),ip_port)
if inp == 'exit':
print('关闭连接')
break
data, addr = s.recvfrom(1024)
print("服务端%s响应:%s"%(addr,data.decode()))
s.close()
if __name__ == '__main__':
ip_port = ('127.0.0.1', 9999)
socket_client(ip_port)

启动实例
image

posted @ 2022-07-22 09:23 Harry_666 阅读(307) 评论(0) 推荐(0) 编辑
摘要: 前言 日志是对于软件执行所发生的事件的一种追踪记录方式。日常使用过程中对代码执行的错误和问题会进行查看日志来分析定位问题所在。平常编写代码以及调试也经常用到。通常的新手的做法是直接print打印,但是打印的结果只在控制台显示。今天我们学习一种高级的日志打印和记录模块logging。 logging提 阅读全文 »
posted @ 2021-01-03 22:17 Harry_666 阅读(431) 评论(0) 推荐(0) 编辑
摘要: ##前言 民意测验机构盖洛普从2012年起,每年都会在联合国计划下发布《世界幸福指数报告》,报告会综合两年内150多个国家的国民对其所处社会、城市和自然环境等因素进行评价后,再根据他们所感知的幸福程度对国家进行排名。 《世界幸福指数报告》的编撰主要依赖于对150多个国家的1000多人提出一个简单的主 阅读全文 »
posted @ 2020-12-16 22:41 Harry_666 阅读(1415) 评论(0) 推荐(1) 编辑
摘要: ##前言 正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本 阅读全文 »
posted @ 2020-11-26 22:12 Harry_666 阅读(3082) 评论(0) 推荐(3) 编辑
摘要: 系统环境: centos 7.1 使用模式:命令模式 使用工具:xshell5 、 xftp5 安装mysql前必须删除干净旧的安装包和残留文件,否则安装会失败 查看旧的安装包 rpm -qa | grep mysql 删除旧的安装包 rpm -ev --nodeps mysql-community 阅读全文 »
posted @ 2018-11-14 22:33 Harry_666 阅读(5381) 评论(0) 推荐(0) 编辑
摘要: 最近使用jenkins远程拷贝的免密访问遇到不少问题,其中主要原因还是对ssh的加密解密不太熟悉,于是便有了这篇文章。 首先我们来了解什么是公钥和私钥。 私钥 服务器上经过rsa算法生成的私钥。与公钥是一对的密钥对,用于连接其他服务器用。 公钥 服务器上经过rsa算法生成的公钥。与私钥是一对的密钥对 阅读全文 »
posted @ 2022-07-22 08:53 Harry_666 阅读(413) 评论(0) 推荐(0) 编辑
摘要: devops是什么? DevOps 对团队意味着什么?DevOps 使以前孤立的角色(开发、IT 运营、质量工程和安全)可以协调和协作,以生产更好、更可靠的产品。通过采用 DevOps 文化、做法和工具,团队能够更好地响应客户需求,增强对所构建应用程序的信心,更快地实现业务目标。 devops好处? 阅读全文 »
posted @ 2022-07-22 08:41 Harry_666 阅读(59) 评论(0) 推荐(0) 编辑
摘要: pytest自带报告 pytest可以生成junit格式的xml报告和HTML报告,命令如下: pytest test_demo.py --junitxml=report.xml pytest test_demo.py --html=report.html #需要安装插件:pip install p 阅读全文 »
posted @ 2022-07-22 08:36 Harry_666 阅读(687) 评论(0) 推荐(0) 编辑
摘要: jenkins+github+python 首先你需要写好自动化的测试用例,目前已经完成了公司的接口用例,所以进行持续进行到jenkins。方便进行冒烟和回归测试,同时也可以给开发小伙伴进行自测。 安装 安装git 安装jenkins 安装测试代码执行的第三方包 测试代码在Jenkins服务器能直接 阅读全文 »
posted @ 2022-07-22 08:32 Harry_666 阅读(308) 评论(0) 推荐(0) 编辑
摘要: linux的kill、killall、killall5命令区别 1.kill kill命令可以杀死指定PID的进程。 也就是说,如果我们要杀死一个我们只知道名称的的进程,我们需要两个步骤: 通过使用ps命令,并且配合使用grep命令,找到进程的PID 通过kill命令kill -9 ,杀死进程 2. 阅读全文 »
posted @ 2022-07-22 08:19 Harry_666 阅读(455) 评论(0) 推荐(0) 编辑
摘要: faker生成随机时间并按格式转换 但是生成的时间太久远了,不符合真实场景,于是我查询了文档 时间范围内的随机时间: from faker import Faker from datetime import datetime f = Faker() f.date_time_between(datet 阅读全文 »
posted @ 2022-07-22 08:17 Harry_666 阅读(355) 评论(0) 推荐(0) 编辑
摘要: 简介:持续集成、持续交付不仅可以提示开发效率,还可以节省很多测试和运维的成本。其中,Jenkins是自动化部署中最流行的工具,尤其是Docker+Jenkins的完美搭配,每个人都应该掌握这两个工具的使用 环境配置 ● 操作系统:centos7 docker下载jenkins docker pull 阅读全文 »
posted @ 2022-07-12 10:36 Harry_666 阅读(3232) 评论(0) 推荐(0) 编辑
摘要: 基础结构 一般的,Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。 FROM: 格式为 FROM 或FROM :。 第一条指令必须为 FROM 指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令(每个镜像一次) M 阅读全文 »
posted @ 2022-07-12 10:24 Harry_666 阅读(107) 评论(0) 推荐(0) 编辑
摘要: 操作镜像 获取镜像:docker pull docker pull busybox:latest 查看镜像:docker images 启动镜像:docker run 如果没有镜像则先下载镜像,然后在通过镜像启动容器 docker run -itd -p 80:80 --name=box -v /h 阅读全文 »
posted @ 2022-07-12 10:08 Harry_666 阅读(115) 评论(0) 推荐(0) 编辑
摘要: docker概念 docker是基于go语言实现的容器项目,docker构建思想:build,ship and run any app,anywhere,即一次封装,到处运行。 docker在linux容器基础上进行了进一步的优化。使得docker容器更像是一种轻量级的沙盒。 docker优势 ● 阅读全文 »
posted @ 2022-07-12 09:10 Harry_666 阅读(35) 评论(0) 推荐(0) 编辑
摘要: 股市打新债卷,只要中签基本是稳赚不赔,但是也不是每天都有,天天看也麻烦。于是便有了下面的自动化程序。 import requests import time import smtplib from datetime import datetime from email.mime.text impor 阅读全文 »
posted @ 2022-07-12 09:07 Harry_666 阅读(243) 评论(0) 推荐(0) 编辑
摘要: crontab自动定时执行 环境:centos7 编辑: crontab -e * * * * * program - - - - - —执行程序语法 | | | | | | | | | + 星期中星期几 (0 - 6) (星期天 为0) | | | + 月份 (1 - 12) | | + 一个月中 阅读全文 »
posted @ 2022-07-12 09:00 Harry_666 阅读(182) 评论(0) 推荐(0) 编辑
摘要: jenkins使用用户多起来时必须采取一定的权限管理机制,否则容易出现失控事故。 jenkins需要安装插件来管理用户权限,安装步骤如下 Manage Jenkins - Manage Plugins - 可选插件中安装 Role-based Authorization Strategy 安装完成重 阅读全文 »
posted @ 2022-06-01 10:58 Harry_666 阅读(3445) 评论(0) 推荐(1) 编辑
摘要: pytest可以生成junit格式的xml报告和HTML报告,命令如下: pytest test_demo.py --junitxml=report.xml pytest test_demo.py --html=report.html #需要安装插件:pip install pytest-html 阅读全文 »
posted @ 2022-06-01 10:57 Harry_666 阅读(150) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示