python --------------网络(socket)编程
一、网络协议
客户端/服务器架构
1.硬件C/S架构(打印机)
2.软件C/S架构(互联网中处处是C/S架构):B/S架构也是C/S架构的一种,B/S是浏览器/服务器
C/S架构与socket的关系:我们用socket就是为了完成C/S架构的开发
osi七层
引子:
须知一个完整的计算机系统是由硬件、操作系统、应用软件三者组成,具备了这三个条件,一台计算机系统就可以自己跟自己玩了(打个单机游戏,玩个扫雷啥的)
如果你要跟别人一起玩,那你就需要上网了,什么是互联网?
互联网的核心就是由一堆协议组成,协议就是标准,比如全世界人通信的标准是英语
如果把计算机比作人,互联网协议就是计算机界的英语。所有的计算机都学会了互联网协议,那所有的计算机都就可以按照统一的标准去收发信息从而完成通信了。
人们按照分工不同把互联网协议从逻辑上划分了层级,
详见网络通信原理:http://www.cnblogs.com/linhaifeng/articles/5937962.html
为何学习socket一定要先学习互联网协议?
首先C/S架构是基于网络通信的
然后网络的核心即一堆网络协议,也就是协议标准。如果你想开发一款基于网络通信的软件,就必须遵循这些标准
socke层
二、socket是什么?
socket是应用层与TCP/IP协议通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的。
三、基于TCP协议的socket
套接字的分类:
基于文件类型的套接字家族:AF_UNIX(在Unix系统上,一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程同时运行在同一机器,可以通过访问同一个文件系统间接完成通信)
基于网络类型的套接字家族:AF_INET (python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我们只使用AF_INET)
套接字的工作流程:
下面我们举个打电话的小例子来说明一下
如果你要给你的一个朋友打电话,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理。
(如果你去一家餐馆吃饭,假设哪里的老板就是服务端,而你自己就是客户端,当你去吃饭的时候,你肯定的知道那个餐馆,也就是服务端的地址吧,但是对于你自己来说,餐馆的老板不需要知道你的地址吧)
套接字函数
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 1.服务端套接字函数
phone.bind('主机ip地址',端口号) #绑定到(主机,端口号)套接字
phone.listen() #开始TCP监听
phone.accept() #被动接受TCP客户的连接,等待连接的到来
服务端套接字函数
2.客户端套接字函数
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
phone.connect() #主动连接服务端的ip和端口
phone.connect_ex() #connect()函数的扩展版本,出错的时候返回错码,而不是抛出异常
客户端套接字函数
3.服务端和客户端的公共用途的嵌套字函数
phone.recv() #接受TCP数据
phone.send() #发送TCP数据
phone.recvfrom() #接受UDP数据
phone.sendto() #发送UDP数据
phone.getpeername() #接收到当前套接字远端的地址
phone.getsockname() #返回指定套接字的参数
phone.setsockopt() #设置指定套接字的参数
phone.close() #关闭套接字
服务端和客户端的公共用途的嵌套字函数
面向锁的套接字方法
phone.setblocking() #设置套接字的阻塞与非阻塞模式
phone.settimeout() #设置阻塞套接字操作的超时时间
phone.gettimeout() #得到阻塞套接字操作的超时时间
面向锁的套接字方法
面向文件的套接字函数
phone.fileno() # 套接字的文件描述符
phone.makefile() #创建一个与该套接字相关的文件
面向文件的套接字函数
TCP是基于链接的,必须先启动服务器,然后再启动客户端去链接服务端
服务端:
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #可以多次启动
#执行多次的时候会报错,那么怎么办呢、?就在绑卡前面加上上面那句setsockopt方法就ok了
phone.bind(('192.168.20.44',8080))#绑定手机卡(ip,端口)
# 端口号在1024以前的是系统用的,1024以后的都是你自己写的程序去定义的端口 print('starting run......')
phone.listen(5) #开机 5代表的是最多挂起5个,也可以好多个
while True: #链接循环
coon,client_addr=phone.accept()#等待接电话,(coon是建立的链接,客户端的ip和端口号组成的元组)
print(coon,client_addr) #收发消息
while True: #通信循环
try: #如果不加try...except ,就会报错,因为它不知道你什么时候断开链接的,服务器还以为你在运行
data = coon.recv(1024) #收了1024个字节的消息
print('client data 收到消息:%s'%data.decode('utf-8'))
coon.send(data.upper()) #发消息
except Exception: #因为你不知道客户端什么时候断开链接,
break
coon.close() #挂电话
phone.close() #关机 # 处理逻辑错误的两种方式:
# if 判断
# try...except 异常处理
# 异常处理
# 当你知道直接错误的条件时就用if判断了
# 当程序错误一定发生,但是你又预知不了它出错的条件是什么的时候,就用try...except
服务端
客户端:
import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
phone.connect(('192.168.20.44',8080)) #直接连接服务端的ip和端口 # 发收消息
while True:
msg = input('>>:').strip() #用户输入
if not msg:continue #如果为空就继续输
phone.send(msg.encode('utf-8')) # 发送你输入的消息
# phone.send('hello'.encode('utf-8'))
data = phone.recv(1024) #在接收一下
print('server back res服务端返回结果:>>%s'%data.decode('utf-8')) phone.close()
客户端
注意:
如果你在重启服务端的时候可能遇到这样的问题:
这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址(如果不懂,请深入研究1.tcp三次握手,四次挥手 2.syn洪水攻击 3.服务器高并发情况下会有大量的time_wait状态的优化方法)。那么怎么解决呢?你也可以这样的
#加入一条socket配置,重用ip和端口 phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8080))
四、基于TCP协议模拟ssh远程执行命令
import socket
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
phone.bind(('192.168.20.44',8081))#绑定手机卡
phone.listen(5)#阻塞的最大个数
print('starting....')
while True:
conn,addr=phone.accept()#等待连接
print(addr,conn)
while True:
cmd=conn.recv(10240)#接收的最大值
# if not cmd :break
print('接收的是:%s'%cmd.decode('utf-8'))
#处理过程
res=subprocess.Popen(cmd.decode('utf-8'),shell=True, #Popen是执行命令的方法
stdout=subprocess.PIPE,
stderr=subprocess.PIPE )
stdout=res.stdout.read()
stuerr=res.stderr.read()
conn.send(stdout+stuerr)
conn.close()
phone.close()
服务端
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('192.168.20.44',8081))#绑定端口
while True:
cmd=input('>>请输入').strip()
if not cmd: continue
phone.send(cmd.encode('utf-8'))
data=phone.recv(10240)
print('返回的是%s'%data.decode('gbk'))
phone.close()
客户端
六、基于UDP协议的socket
from socket import *
udp_server = socket(AF_INET,SOCK_DGRAM)
udp_server.bind(('127.0.0.1',8080)) #绑定
while True:#通讯循环
msg,client_addr= udp_server.recvfrom(1024)
print('收到的消息是:%s'%msg.decode('utf-8'))
udp_server.sendto(msg.upper(),client_addr)
udp_server.close()
服务端
# udp 无链接,所以不需要连接
from socket import *
udp_client = socket(AF_INET,SOCK_DGRAM) while True:
msg = input('>>:').strip()
udp_client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
res,sever_addr = udp_client.recvfrom(1024)
print('返回的结果是:%s'%res.decode('utf-8'))
udp_client.close()
客户端
基于UDP协议的socket的应用(模拟QQ聊天)
from socket import *
udp_server= socket(AF_INET,SOCK_DGRAM)
udp_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
udp_server.bind(('127.0.0.1',8080))
print('start running...') while True:
qq_msg,addr = udp_server.recvfrom(1024)
print('来自[%s:%s]的一条消息:\033[44m%s\033[0m'%(addr[0],addr[1],qq_msg.decode('utf-8')))
back_msg = input('回复消息:>>').strip()
udp_server.sendto(back_msg.encode('utf-8'),addr)
udp_server.close()
服务端
from socket import *
udp_client = socket(AF_INET,SOCK_DGRAM)
qq_name_dic = {
'房得成':('127.0.0.1',8080),
'陈凤琴':('127.0.0.1',8080),
'王雅玲':('127.0.0.1',8080),
'喜洋洋':('127.0.0.1',8080)
}
while True:
qq_name = input('请输入聊天对象:>>').strip()
if qq_name not in qq_name_dic: continue
while True:
msg = input('请输入消息,回车发送:').strip()
if msg=='quit':break
if not msg or not qq_name or qq_name not in qq_name_dic:continue
udp_client.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
back_msg,addr = udp_client.recvfrom(1024)
print('来自[%s:%s]的一条消息:\033[41m%s\033[0m'%(addr[0],addr[1],back_msg.decode('utf-8')))
udp_client.close()
客户端
运行结果截图
五、subprocess子进程模块
import subprocess
#Popen方法是用来执行系统命令的,直接把结果打印到终端了
res =subprocess.Popen(r'dir',shell=True,
#r'dsfsdfr',shell=True,
# stdin= #标准输入(不常用)
stdout=subprocess.PIPE,#stdout 标准输出
stderr=subprocess.PIPE) #stderr 标准错误
# 拿到的是‘gbk’编码的结果,
# 这个命令可能有正确结果,也可能有错误结果
print(res.stdout.read().decode('gbk'))
print('========')
print(res.stdout.read().decode('gbk')) #说明只能读一次
print(res.stderr.read().decode('gbk')) #如果是错误的就会提示
subprocess
六、struct模块
#该模块可以把一个类型,如数字,转成固定长度的bytes类型
import struct
# res = struct.pack('i',12345)
# print(res,len(res),type(res)) #长度是4 res2 = struct.pack('i',12345111)
print(res2,len(res2),type(res2)) #长度也是4 unpack_res =struct.unpack('i',res2)
print(unpack_res) #(12345111,)
# print(unpack_res[0]) #12345111
struct
python --------------网络(socket)编程的更多相关文章
- python网络socket编程
一.服务端 #!/usr/bin/python # -*- coding: UTF-8 -*- import socket import sys from thread import * HOST = ...
- 转:Python 的 Socket 编程教程
这是用来快速学习 Python Socket 套接字编程的指南和教程.Python 的 Socket 编程跟 C 语言很像. Python 官方关于 Socket 的函数请看 http://docs. ...
- Python 3 socket 编程
Python 3 socket编程 一 客户端/服务器架构 互联网中处处是C/S架构 1.C/S结构,即Client/Server(客户端/服务器)结构 2.在互联网中处处可见c/s架构 比如说浏览器 ...
- 最基础的Python的socket编程入门教程
最基础的Python的socket编程入门教程 本文介绍使用Python进行Socket网络编程,假设读者已经具备了基本的网络编程知识和Python的基本语法知识,本文中的代码如果没有说明则都是运行在 ...
- python之socket编程(一)
socket之前我们先来熟悉回忆几个知识点. OSI七层模型 OSI(Open System Interconnection)参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标 ...
- Python:socket编程教程
ocket是基于C/S架构的,也就是说进行socket网络编程,通常需要编写两个py文件,一个服务端,一个客户端. 首先,导入Python中的socket模块: import socket Pytho ...
- UDP协议网络Socket编程(java实现C/S通信案例)
我的博客园:https://www.cnblogs.com/chenzhenhong/p/13825286.html 我的CSDN博客:https://blog.csdn.net/Charzous/a ...
- Java:基于TCP协议网络socket编程(实现C/S通信)
目录 一.前言:TCP原理简介 二.Socket编程通信 三.TCP服务器端(具体代码) 四.TCP客户端(具体代码) 五.通信效果演示 六."创意"机器人:价值一个亿的AI核心代 ...
- java多线程实现TCP网络Socket编程(C/S通信)
目录 开篇必知必会 一.多线程技术 二.实现多线程接收 1.单线程版本 2.多线程版本 三.多线程与进程的关系 四.客户端界面完整代码 五.多线程通信对比 最后 开篇必知必会 在前一篇<Java ...
- python网络-Socket之TCP编程(26)
一.TCP简介 1.TCP介绍 TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的.可靠的.基于字节流的传输层通信协议. TC ...
随机推荐
- Factorized Hidden Variability Learning For Adaptation Of Short Duration Language Identification Models
基于因子分解的隐层变量学习,应用于短语句语种识别模型的自适应 LFVs(Language Feature Vectors,语种特征向量)[11],与BSVs(Bottleneck Speake ...
- Mysql-5.7.20-winx64绿色版安装步骤
Mysql-5.7.20-winx64绿色版安装步骤 1. 下载 mysql-5.7.20-winx64.zip 2.解压 解压到指定目录: C:\AppDate\mysql-5.7.20-winx6 ...
- python 小数据池,is and "==",decode ,encode
一:小数据池 1.python运行中的缓存: 2.目的:缓存我们字符串,整数,布尔值.在使用的时候不需要创建过多的对象 3.python 缓存数据:缓存:int, str, bool. ...
- 使用Retrofit时常用到的注解
- 计算价格, java中浮点数精度丢失的解决方案
计算价格, java中浮点数精度丢失的解决方案
- python - 中文编码/ASCII
Python 中文编码 为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5. GB2312(1980年)一共收录了7445个字符,包括6763个汉子和682个其他符号. ...
- Django中的csrf基础了解
简介 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对于django中设置防跨站请求伪造功能有 ...
- SpringBoot--配置详解
SpringBoot使用了一个全局的配置文件application.properties,放在src/mian/resource目录下或者类路径的/config下.springboot的全局配置文件的 ...
- 阿里云ECS centos7配置tomcat
准备:创建好developer目录和tomcat子目录 1.在 http://tomcat.apache.org/download-80.cgi 下载tomcat,通过Xftp拷贝到tomcat目录 ...
- 第一次发博,发个简单的Java程序发送手机短信验证
最近在准备一个项目,想的登录时候用手机验证,就通过上网查阅了一下手机验证的实现方法,原来超级简单,下面将一步一步介绍. 1.去中国网建注册一个账号密码,首次注册送五条免费短信和3条免费彩信.具体的网址 ...