Python_oldboy_自动化运维之路_socket编程(十)

链接:http://www.cnblogs.com/linhaifeng/articles/6129246.html

1.osi七层

引子:

须知一个完整的计算机系统是由硬件、操作系统、应用软件三者组成,具备了这三个条件,一台计算机系统就可以自己跟自己玩了(打个单机游戏,玩个扫雷啥的)

如果你要跟别人一起玩,那你就需要上网了(访问个黄色网站,发个黄色微博啥的),互联网的核心就是由一堆协议组成,协议就是标准,全世界人通信的标准是英语,如果把计算机比作人,互联网协议就是计算机界的英语。所有的计算机都学会了互联网协议,那所有的计算机都就可以按照统一的标准去收发信息从而完成通信了。人们按照分工不同把互联网协议从逻辑上划分了层级,详见我另一篇博客

网络通信原理:http://www.cnblogs.com/linhaifeng/articles/5937962.html

为何学习socket一定要先学习互联网协议:

1.首先:本节课程的目标就是教会你如何基于socket编程,来开发一款自己的C/S架构软件

2.其次:C/S架构的软件(软件属于应用层)是基于网络进行通信的

3.然后:网络的核心即一堆协议,协议即标准,你想开发一款基于网络通信的软件,就必须遵循这些标准。

4.最后:就让我们从这些标准开始研究,开启我们的socket编程之旅

2.socket层

3.socket是什么

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

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

也有人将socket说成ip+port,ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序,ip地址是配置到网卡上的,而port是应用程序开启的,ip与port的绑定就标识了互联网中独一无二的一个应用程序

而程序的pid是同一台机器上不同进程或者线程的标识

4.套接字的工作流程

一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。    生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定。

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

socket()模块函数用法

案例1:基于tcp的一次套接字的通信:

# -*- coding: UTF-8 -*-
#blog:http://www.cnblogs.com/linux-chenyang/

import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #socket.AF_INET,叫做基于网络的地址家族 socket.SOCK_STREAM代表TCP协议
                                                       #相当于买手机
phone.bind((‘127.0.0.1‘,8081))                           #相当于插入卡,唯一的标示

phone.listen(5)                                        #相当于开机 5表示等待别人连接,假如我这边通话中,让他等待我完成在连接

conn,addr=phone.accept()                               #接电话conn表示线路,addr表示客户端地址
print(‘tcp的连接‘,conn)
print(‘客户端的地址‘,addr)

data=conn.recv(1024)                                   #收消息,收1024个字节大小的内容,收到的内容是bytes格式
print(‘from client msg:%s‘ %data)                      #打印传过来的消息

conn.send(data.upper())                                #发消息,将传过来的值转换成大写

conn.close()                                           #挂电话
phone.close()                                          #关手机

socket服务端

# -*- coding: UTF-8 -*-
#blog:http://www.cnblogs.com/linux-chenyang/
import socket

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect((‘127.0.0.1‘,8081))          #拨通电话

client.send(‘hello‘.encode(‘utf-8‘))        #客户发送消息

date =  client.recv(1024)
print(date)

client.close()

socket客户端

#先执行服务端在执行客户端

#服务端输出:
tcp的连接 <socket.socket fd=268, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=(‘127.0.0.1‘, 8081), raddr=(‘127.0.0.1‘, 54345)>
客户端的地址 (‘127.0.0.1‘, 54345)
from client msg:b‘hello‘

#客户端输出:
b‘HELLO‘

执行结果

案例2:循环的socket

# -*- coding: UTF-8 -*-
#blog:http://www.cnblogs.com/linux-chenyang/
#验证:将一个客户端断开连接,另外一个自动连接
import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)    #假如不加这行参数,假如运行过一次服务器在运行就表示端口被占用,报错
phone.bind((‘127.0.0.1‘,8081))

phone.listen(5)

while True:                             #链接循环
    conn,addr=phone.accept()
    print(‘client:‘,addr)
    while True:
        try:                                 #异常捕捉,假如有异常,然后就断掉此次循环
            data=conn.recv(1024)
            print(‘from client msg:%s‘ %data)
            conn.send(data.upper())
        except Exception:                   #万能的错误,假如上面有一个异常,就执行下面的break代码
            break

    conn.close()
phone.close()

socket服务端

# -*- coding: UTF-8 -*-
#blog:http://www.cnblogs.com/linux-chenyang/

import socket

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect((‘127.0.0.1‘,8081))          #拨通电话

while True:
    msg = input(‘>>:‘)
    client.send(msg.encode(‘utf-8‘))        #客户发送消息

    date =  client.recv(1024)
    print(date)

client.close()

socket客户端1

# -*- coding: UTF-8 -*-
#blog:http://www.cnblogs.com/linux-chenyang/
import socket

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect((‘127.0.0.1‘,8081))          #拨通电话

while True:
    msg = input(‘>>:‘)
    client.send(msg.encode(‘utf-8‘))        #客户发送消息

    date =  client.recv(1024)
    print(date)

client.close()

socket客户端2

#服务端
C:\Python35\python3.exe D:/pycharm/s16/day7/循环的socket服务端.py
client: (‘127.0.0.1‘, 58308)
from client msg:b‘ls‘
from client msg:b‘test‘
from client msg:b‘\xe8\xb5\xb0\xe4\xba\x86‘
client: (‘127.0.0.1‘, 58313)
from client msg:b‘ls‘
from client msg:b‘ss‘

#客户端1:将客户端1断掉后发现服务端可以看到客户端2立马连了上来
C:\Python35\python3.exe D:/pycharm/s16/day7/循环的socket客户端2.py
>>:ls
b‘LS‘
>>:test
b‘TEST‘
>>:走了
b‘\xe8\xb5\xb0\xe4\xba\x86‘
>>:
Process finished with exit code 1

#客户端2
C:\Python35\python3.exe D:/pycharm/s16/day7/循环的socket客户端.py
>>:ls
b‘LS‘
>>:ss
b‘SS‘

执行结果

案例3:循环的socke优化

# -*- coding: UTF-8 -*-
#blog:http://www.cnblogs.com/linux-chenyang/
#验证:将一个客户端断开连接,另外一个自动连接
import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)    #假如不加这行参数,假如运行过一次服务器在运行就表示端口被占用,报错
phone.bind((‘127.0.0.1‘,8081))

phone.listen(5)

while True:                             #链接循环
    conn,addr=phone.accept()
    print(‘client:‘,addr)
    while True:
        try:                                 #异常捕捉,假如有异常,然后就断掉此次循环
            data=conn.recv(1024)
            if not data:break               #针对linux,客户端断开链接的异常处理
            print(‘from client msg:%s‘ %data)
            conn.send(data.upper())
        except Exception:                   #万能的错误,假如上面有一个异常,就执行下面的break代码
            break

    conn.close()
phone.close()

socket服务端

# -*- coding: UTF-8 -*-
#blog:http://www.cnblogs.com/linux-chenyang/

import socket

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

client.connect((‘127.0.0.1‘,8081))          #拨通电话

while True:
    msg = input(‘>>:‘)
    if not msg:continue                     #假如不输入这条内容,当msg直接为空时,会发生阻塞,客户端send一个空,服务器会一直等着收,不会send
    client.send(msg.encode(‘utf-8‘))        #客户发送消息
    print(‘===========has send=========‘)

    date =  client.recv(1024)
    print(‘===========has recv=========‘)
    print(date)

client.close()

socket客户端

案例4:socke模拟远程执行命令

import socket
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)    #假如不加这行参数,假如运行过一次服务器在运行就表示端口被占用,报错
phone.bind((‘127.0.0.1‘,8081))
phone.listen(5)
while True:
    conn,addr=phone.accept()
    print(‘client:‘,addr)
    while True:
        try:
            cmd=conn.recv(1024)
            print(‘-------shou dao--- ‘)
            if not cmd:break
            print(‘from client msg:%s‘ %cmd)

            res=subprocess.Popen(cmd.decode(‘utf-8‘),
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE
                             )

            err=res.stderr.read()
            if err:
                back_msg=err
            else:
                back_msg=res.stdout.read()

            conn.sendall(back_msg)

        except Exception:
            break

    conn.close()
phone.close()

socket服务端

import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((‘127.0.0.1‘,8081))

while True:
    cmd = input(‘>>:‘).strip()
    if not cmd:continue

    client.send(cmd.encode(‘utf-8‘))
    print(‘send chenggong‘)
    res = client.recv(1024)
    print(res.decode(‘gbk‘))

socke客户端

#服务端
client: (‘127.0.0.1‘, 61320)
-------shou dao---
from client msg:b‘dir‘

#客户端
C:\Python35\python3.exe D:/pycharm/s16/day7/远程执行命令客户端.py
>>:dir
send chenggong
 驱动器 D 中的卷是 Data
 卷的序列号是 EE42-C3C3

 D:\pycharm\s16\day7 的目录

2017/03/08  21:35    <DIR>          .
2017/03/08  21:35    <DIR>          ..
2017/03/08  17:23               337 socket客户端.py
2017/03/08  17:23             1,222 socket服务端.py
2017/03/08  14:39               697 为什么要有类,对象.py
2017/03/07  17:24               690 多态与多态性.py
2017/03/07  19:22               780 子类调用父类的方法.py
2017/03/06  17:51             1,268 对象之间的交互.py
2017/03/07  17:58             1,532 封装.py
2017/03/08  20:06               652 循环的socket客户端.py
2017/03/08  17:49               380 循环的socket客户端2.py
2017/03/08  20:09             1,062 循环的socket服务端.py
2017/03/07  15:59               939 抽象类.py
2017/03/07  15:03               741 接口与归一化设计.py
2017/03/07  18:57             1,376 特性_set_get.py
2017/03/07  18:23             1,337 特性(property).py
2017/03/06  16:09                 2 笔记
2017/03/06  17:39             1,719 类与对象.py
20

#备注:假如执行的时候客户端发出去了,服务端没有收到,但是已经连接上了,已经打印客户端的信息,那么就换个端口试试,原因:未解

执行结果

时间: 2024-12-21 15:56:46

Python_oldboy_自动化运维之路_socket编程(十)的相关文章

Python_oldboy_自动化运维之路(一)

python简介: Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构. python特点: 1.易于学习:Python有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单. 2.易于阅读:Python代码定义的更清晰. 3.易于维护:Python的成功在于它的源代码是相当容易维护的. 4.一个广泛的标准库:Python的最大

Python_oldboy_自动化运维之路_paramiko,mysql(十二)

本节内容: paramiko mysql 1.paramiko http://www.cnblogs.com/wupeiqi/articles/5095821.html paramiko是一个模块,socket和ssh协议,利用这个模块就可以用python代码实现远程服务器操作 ansible底层就是用的这个模块 功能: a.使用用户名密码:命令,文件 b.使用用户名秘钥:命令,文件 c.执行创建session 1.基于用户名密码连接: import paramiko # 创建SSH对象 ssh

Python_oldboy_自动化运维之路(二)

循环: [for循环] 1 for i in range(5): 2 print ("look", i) 1. 输入密码场景,判断用户名和密码都输入成功,则显示登陆成功,用户名是xiaoyu则不让登陆 1 user = "chenlijun" 2 passwd = "lijun" 3 newuser = input("name:") 4 newpasswd = input("passwd:") 5 if u

Python_oldboy_自动化运维之路(三)

本节内容 列表,元组,字典 1.列表,元组,字典 [列表] 1.定义列表 1 names = ['Alex',"Tenglan",'Eric'] 2.通过下标访问列表中的元素,下标从0开始计数 1 >>> names[0] 2 'Alex' 3 >>> names[2] 4 'Eric' 5 >>> names[-1] 6 'Eric' 7 >>> names[-2] #还可以倒着取 8 'Tenglan' 切片:

Python_oldboy_自动化运维之路_面向对象2(十)

本节内容: 面向对象程序设计的由来 什么是面向对象的程序设计及为什么要有它 类和对象 继承与派生 多的态与多态性 封装 静态方法和类方法 面向对象的软件开发 1.面向对象程序设计的由来 见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.html 2.什么是面向对象的程序设计及为什么要有它 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优点是:极大的降低了程

Python_oldboy_自动化运维之路_线程,进程,协程(十一)

本节内容: 线程 进程 协程 IO多路复用 自定义异步非阻塞的框架 线程和进程的介绍: 举个例子,拿甄嬛传举列线程和进程的关系: 总结:1.工作最小单元是线程,进程说白了就是提供资源的 2.一个应用程序至少有一个进程,一个进程里至少有一个线程 3.应用场景:io密集型适合用多线程,计算密集型(cpu)适合用多进程 4.GIL:全局解释器锁,作用:保证同一个进程中只能有一个线程同时被调用 5.python的一个诟病:前提是被cpu调度,因为有GIL,一个应用只有一个进程,纵容有多个线程,也体现不出

python自动化运维之路~DAY7

python自动化运维之路~DAY7 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.客户端/服务器架构 C/S 架构是一种典型的两层架构,其全称是Client/Server,即客户端服务器端架构,其客户端包含一个或多个在用户的电脑上运行的程序,而服务器端有两种,一种是数据库服务器端,客户端通过数据库连接访问服务器端的数据:另一种是Socket服务器端,服务器端的程序通过Socket与客户端的程序通信. C/S 架构也可以看做是胖客户端架构.因为客户端需要实现绝大多数的业务

python自动化运维之路~DAY10

python自动化运维之路~DAY10 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

python自动化运维之Socket网络编程

1.Socket      socket起源于Unix,而Unix/Linux基本哲学之一就是"一切皆文件",对于文件用[打开][读写][关闭]模式来操作.socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭)基本上,Socket 是任何一种计算机网络通讯中最基础的内容.例如当你在浏览器地址栏中输入 http://www.cnblogs.com/ 时,你会打开一个套接字,然后连接到 http://www.cnb