经过近一个半月的学习我们已经度过了python基础的阶段,今天我们开始学习python网络编程,没有难以理解的逻辑,更注重的是记忆。

本篇导航:

对网络协议和基础没有概念的可以在阅读本文前预习计算机基础3、网络协议:http://www.cnblogs.com/liluning/p/7170799.html

一、客户端/服务器架构

1、C/S结构,即Client/Server(客户端/服务器)结构

2、我们在互联网中处处可见c/s架构比如说浏览器,qq,lol,视频软件。。。

3、我们学习socket就是为了c/s架构的开发


二、scoket与网络协议

首先我们需要实现网络通信必然需要多网络协议有着深刻的了解。而我们做开发如果把每一点都搞清楚太过于耗费精力,所以我们才有了scoket

socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

所以,我们无需深入理解tcp/udp协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵循tcp/udp标准的


三、套接字

套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。

1、基于文件类型的套接字:AF_UNIX

unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信

2、基于网络类型的套接字:AF_INET

还有AF_INET6被用于ipv6,还有一些其他的地址家族,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET

3、套接字函数的认识

首先我们要知道所有的函数使用都需要导入socket模块

1)socket()模块

import socket
获取tcp/ip套接字
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 获取udp/ip套接字
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

2)服务端套接字函数

bind()    绑定(主机,端口号)到套接字
listen() 开始TCP监听
accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来

3)客户端套接字函数

connect()     主动初始化TCP服务器连接
connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

4)公共用途的套接字函数

recv()            接收TCP数据
send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
recvfrom() 接收UDP数据
sendto() 发送UDP数据
getpeername() 连接到当前套接字的远端的地址
getsockname() 当前套接字的地址
getsockopt() 返回指定套接字的参数
setsockopt() 设置指定套接字的参数
close() 关闭套接字

5)面向锁的套接字函数

setblocking()     设置套接字的阻塞与非阻塞模式
settimeout() 设置阻塞套接字操作的超时时间
gettimeout() 得到阻塞套接字操作的超时时间

6)面向文件的套接字函数

fileno()          套接字的文件描述符
makefile() 创建一个与该套接字相关的文件

四、基于tcp的套接字代码实现

前面一次性近二十个函数是不是看蒙蔽了 来看看实际应用其实应用很简单

tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

tcp服务端

ss = socket()      #创建服务器套接字
ss.bind() #把地址绑定到套接字
ss.listen() #监听链接
while True : #服务器无限循环
conn,client_addr=ss.accept() #接受客户端链接
while True : #通讯循环
conn.recv()/cs.send() #对话(接收与发送)
conn.close() #关闭客户端套接字
ss.close() #关闭服务器套接字(可选)

tcp客户端

cs = socket()    # 创建客户套接字
cs.connect() # 尝试连接服务器
while True : # 通讯循环
cs.send()/cs.recv() # 对话(发送/接收)
cs.close() # 关闭客户套接字

1、socket通信流程与打电话流程类似以此为例:

服务端:

import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
s.bind('127.0.0.1',8080) #手机插卡
s.listen(5) #开机 #print('starting...')
conn,addr=s.accept() #等电话 (链接,客户的的ip和端口组成的元组)
#print(conn,addr) data=conn.recv(1024) #接收
print('client data: <%s>' %data)
conn.send(data.upper()) #发送 conn.close() #挂电话
s.close() #关机

客户端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.connect(('127.0.0.1',8080)) #绑定手机卡 #发,收消息
phone.send('hello'.encode('utf-8'))
data=phone.recv(1024)
print('server back res:<%s>' %data) phone.close()

2、加上链接循环与通信循环

服务端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.bind(('127.0.0.1',8081)) #绑定手机卡
phone.listen(5) #开机 最多挂起5个服务 print('starting...')
while True: #链接循环
conn,client_addr=phone.accept() #等电话 (链接,客户的的ip和端口组成的元组)
print('-------->',conn,client_addr) #收,发消息
while True:#通信循环
try:
data=conn.recv(1024)
if not data:break #针对linux
print('client data: <%s>' %data)
conn.send(data.upper())
except Exception:
break
conn.close() #挂电话
phone.close() #关机

客户端(可以有几个客户端一起链接后面的被挂起前一个断开后立马链接):

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
phone.connect(('127.0.0.1',8081)) #绑定手机卡 #发,收消息
while True:
msg=input('>>: ').strip()
if not msg:continue
phone.send(msg.encode('utf-8'))
data=phone.recv(1024)
print('server back res:<%s>' %data) phone.close()

3、模拟ssh远程模拟命令

服务端:

import socket
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8082))
phone.listen(5) print('starting...')
while True:
conn,client_addr=phone.accept()
print('-------->',conn,client_addr) while True:
try:
cmd=conn.recv(1024)
#if not cmd:break #针对linux
#执行cmd命令,拿到cmd的结果,结果应该是bytes类型
#。。。。
res = subprocess.Popen(cmd.decode('utf-8'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout=res.stdout.read()
stderr=res.stderr.read() #发送命令的结果
conn.send(stdout+stderr)
except Exception:
break
conn.close() #挂电话
phone.close() #关机

客户端:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8082)) while True:
cmd=input('>>: ').strip()
if not cmd:continue
phone.send(cmd.encode('utf-8'))
cmd_res=phone.recv(1024)
print(cmd_res.decode('gbk'))
phone.close()

五、异常解决(了解)

解决方法:

#加入一条socket配置,重用ip和端口

phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8080))
发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
vi /etc/sysctl.conf 编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30 然后执行 /sbin/sysctl -p 让参数生效。 net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭; net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭; net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。 net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间

linux系统方法


六、subprocess模块(简单介绍)

允许你去创建一个新的进程让其执行另外的程序,并与它进行通信,获取标准的输入、标准输出、标准错误以及返回码等

Popen类

subprocess模块中定义了一个Popen类,通过它可以来创建进程,并与其进行复杂的交互。查看一下它的构造函数:

__init__(self, args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None, preexec_fn=None,
close_fds=False, shell=False, cwd=None, env=None,
universal_newlines=False, startupinfo=None,
creationflags=0)

主要参数说明: 
args:args should be a string, or a sequence of program arguments.也就是说必须是一个字符串或者序列类型(如:字符串、list、元组),用于指定进程的可执行文件及其参数。如果是一个序列类型参数,则序列的第一个元素通常都必须是一个可执行文件的路径。当然也可以使用executeable参数来指定可执行文件的路径。

stdin,stdout,stderr:分别表示程序的标准输入、标准输出、标准错误。有效的值可以是PIPE,存在的文件描述符,存在的文件对象或None,如果为None需从父进程继承过来,stdout可以是PIPE,表示对子进程创建一个管道,stderr可以是STDOUT,表示标准错误数据应该从应用程序中捕获并作为标准输出流stdout的文件句柄。

shell:如果这个参数被设置为True,程序将通过shell来执行。 
env:它描述的是子进程的环境变量。如果为None,子进程的环境变量将从父进程继承而来。

实例化:

res = subprocess.Popen(r'dir', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

28、初识socket(subprocess模块)的更多相关文章

  1. python笔记-9(subprocess模块、面向对象、socket入门)

    一.subprocess 模块 1.了解os.system()与os.popen的区别及不足 1.1 os.system()可以执行系统指令,将结果直接输出到屏幕,同时可以将指令是否执行成功的状态赋值 ...

  2. python笔记8 socket(TCP) subprocess模块 粘包现象 struct模块 基于UDP的套接字协议

    socket 基于tcp协议socket 服务端 import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买 ...

  3. python day 9: xlm模块,configparser模块,shutil模块,subprocess模块,logging模块,迭代器与生成器,反射

    目录 python day 9 1. xml模块 1.1 初识xml 1.2 遍历xml文档的指定节点 1.3 通过python手工创建xml文档 1.4 创建节点的两种方式 1.5 总结 2. co ...

  4. Python中使用subprocess模块远程执行命令

    使用subprocess模块执行远程命令 服务端代码 1 import socket 2 import subprocess 3 4 sh_server = socket.socket() 5 sh_ ...

  5. python学习道路(day7note)(subprocess模块,面向对象)

    1.subprocess模块   因为方法较多我就写在code里面了,后面有注释 #!/usr/bin/env python #_*_coding:utf-8_*_ #linux 上调用python脚 ...

  6. 循序渐进Python3(八) -- 0 -- 初识socket

    socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Un ...

  7. s14 第5天 时间模块 随机模块 String模块 shutil模块(文件操作) 文件压缩(zipfile和tarfile)shelve模块 XML模块 ConfigParser配置文件操作模块 hashlib散列模块 Subprocess模块(调用shell) logging模块 正则表达式模块 r字符串和转译

    时间模块 time datatime time.clock(2.7) time.process_time(3.3) 测量处理器运算时间,不包括sleep时间 time.altzone 返回与UTC时间 ...

  8. 1、初识socket

    经过近一个半月的学习我们已经度过了python基础的阶段,今天我们开始学习python网络编程,没有难以理解的逻辑,更注重的是记忆. 对网络协议和基础没有概念的可以在阅读本文前预习计算机基础3.网络协 ...

  9. python网络编程--粘包解决方案 和 subprocess模块

    1.缓冲区:作用:将程序和网络解耦分为输入缓冲区, 输出缓冲区 每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区.write()/send() 并不立即向网络中传输数据,而是先 ...

随机推荐

  1. alpha冲刺1/10

    目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:来自双十一的爱 团队部分 后敬甲(组长) 过去两天完成了哪些任务 文字描述 Alpha版本的任务细分安排 leangoo ...

  2. lrzsz linix 远程文件传输工具。

    安装方法 #yum install lrzsz -y 使用方法 #rz -y 上传指定文档到当前目录

  3. BZOJ1911 [Apio2010]特别行动队 - 动态规划 - 斜率优化

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 UPD(2018-04-01):用Latex重打了公式…… 题意概括 把一个整数序列划分成任意连续的段,使得划分出 ...

  4. Java中常见的排序方式-快速排序(升序)

    [基本思想] 快速排序在元素较多的情况下,排序效率是相当高的.其基本思想是这样: 假设数组为int[] arr = { 49, 38, 65, 97, 76, 13, 27, 22, 26, 41, ...

  5. linux系统虚拟机下安装nginx基础

    虽然安装nginx什么的 .以及如何配置等等一系列的资料案例已经很多了 但是作为菜鸟的我还是搞了半天哈 官网上面也有.但是一些细节方面的并没有说明.导致踩了半天坑才搞好 本案例的系统环境     wi ...

  6. JAXB在Java 9/10并且使用Tomcat 9的问题

    Implementation of JAXB-API has not been found on module path or classpath. JAXB API是java EE 的API,jav ...

  7. day64 django django零碎知识点整理

    本文转载自紫金葫芦,哪吒,liwenzhou.cnblog博客地址 简单了解mvc框架和MTV框架, mvc是一种简单的软件架构模式: m----model,模型 v---view,视图 c---co ...

  8. 【Java】idea找不到符号找不到类,但是却没有错误

    编译错误,Ctrl+Shift+F9 将提示没有符号类的文件打开,右键单独编译一次,再重新打包即可解决: 特别说明:在Java的集成开发环境中,比如Eclipse.IDEA中,有常常有三种与编译相关的 ...

  9. scrapy之Crawspider 腾讯招聘实战案例

    1. 在虚拟机中cd到项目目录,再运行下面代码创建spider文件: scrapy genspider -t crawl test www.baidu.com 2. spider.py代码 impor ...

  10. DDL DML概念 --- Msysql常用命令

    一.DML DML(data manipulation language)数据操纵语言: 就是我们最经常用到的 SELECT.UPDATE.INSERT.DELETE. 主要用来对数据库的数据进行一些 ...