一、网络协议

客户端/服务器架构

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
2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
3 # 1.服务端套接字函数
4 phone.bind('主机ip地址',端口号) #绑定到(主机,端口号)套接字
5 phone.listen() #开始TCP监听
6 phone.accept() #被动接受TCP客户的连接,等待连接的到来
2.客户端套接字函数
2 import socket
3 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
4 phone.connect() #主动连接服务端的ip和端口
5 phone.connect_ex() #connect()函数的扩展版本,出错的时候返回错码,而不是抛出异常
3.服务端和客户端的公共用途的嵌套字函数
2 phone.recv() #接受TCP数据
3 phone.send() #发送TCP数据
4 phone.recvfrom() #接受UDP数据
5 phone.sendto() #发送UDP数据
6 phone.getpeername() #接收到当前套接字远端的地址
7 phone.getsockname() #返回指定套接字的参数
8 phone.setsockopt() #设置指定套接字的参数
9 phone.close() #关闭套接字
 面向锁的套接字方法
2 phone.setblocking() #设置套接字的阻塞与非阻塞模式
3 phone.settimeout() #设置阻塞套接字操作的超时时间
4 phone.gettimeout() #得到阻塞套接字操作的超时时间
面向文件的套接字函数
2 phone.fileno() # 套接字的文件描述符
3 phone.makefile() #创建一个与该套接字相关的文件

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

服务端:

import socket
2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
3 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #可以多次启动
4 #执行多次的时候会报错,那么怎么办呢、?就在绑卡前面加上上面那句setsockopt方法就ok了
5 phone.bind(('192.168.20.44',8080))#绑定手机卡(ip,端口)
6 # 端口号在1024以前的是系统用的,1024以后的都是你自己写的程序去定义的端口
7
8 print('starting run......')
9 phone.listen(5) #开机 5代表的是最多挂起5个,也可以好多个
10 while True: #链接循环
11 coon,client_addr=phone.accept()#等待接电话,(coon是建立的链接,客户端的ip和端口号组成的元组)
12 print(coon,client_addr)
13
14 #收发消息
15 while True: #通信循环
16 try: #如果不加try...except ,就会报错,因为它不知道你什么时候断开链接的,服务器还以为你在运行
17 data = coon.recv(1024) #收了1024个字节的消息
18 print('client data 收到消息:%s'%data.decode('utf-8'))
19 coon.send(data.upper()) #发消息
20 except Exception: #因为你不知道客户端什么时候断开链接,
21 break
22 coon.close() #挂电话
23 phone.close() #关机
24
25
26 # 处理逻辑错误的两种方式:
27 # if 判断
28 # try...except 异常处理
29 # 异常处理
30 # 当你知道直接错误的条件时就用if判断了
31 # 当程序错误一定发生,但是你又预知不了它出错的条件是什么的时候,就用try...except

客户端:

import socket
2 phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
3 phone.connect(('192.168.20.44',8080)) #直接连接服务端的ip和端口
4
5 # 发收消息
6 while True:
7 msg = input('>>:').strip() #用户输入
8 if not msg:continue #如果为空就继续输
9 phone.send(msg.encode('utf-8')) # 发送你输入的消息
10 # phone.send('hello'.encode('utf-8'))
11 data = phone.recv(1024) #在接收一下
12 print('server back res服务端返回结果:>>%s'%data.decode('utf-8'))
13
14 phone.close()

注意:

如果你在重启服务端的时候可能遇到这样的问题:

这个是由于你的服务端仍然存在四次挥手的time_wait状态在占用地址(如果不懂,请深入研究1.tcp三次握手,四次挥手 2.syn洪水攻击 3.服务器高并发情况下会有大量的time_wait状态的优化方法)。那么怎么解决呢?你也可以这样的

1 #加入一条socket配置,重用ip和端口
2
3 phone=socket(AF_INET,SOCK_STREAM)
4 phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
5 phone.bind(('127.0.0.1',8080))

四、基于TCP协议模拟ssh远程执行命令

import socket
2 import subprocess
3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#买手机
4 phone.bind(('192.168.20.44',8081))#绑定手机卡
5 phone.listen(5)#阻塞的最大个数
6 print('starting....')
7 while True:
8 conn,addr=phone.accept()#等待连接
9 print(addr,conn)
10 while True:
11 cmd=conn.recv(10240)#接收的最大值
12 # if not cmd :break
13 print('接收的是:%s'%cmd.decode('utf-8'))
14 #处理过程
15 res=subprocess.Popen(cmd.decode('utf-8'),shell=True, #Popen是执行命令的方法
16 stdout=subprocess.PIPE,
17 stderr=subprocess.PIPE )
18 stdout=res.stdout.read()
19 stuerr=res.stderr.read()
20 conn.send(stdout+stuerr)
21 conn.close()
22 phone.close()
import socket
2
3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
4 phone.connect(('192.168.20.44',8081))#绑定端口
5 while True:
6 cmd=input('>>请输入').strip()
7 if not cmd: continue
8 phone.send(cmd.encode('utf-8'))
9 data=phone.recv(10240)
10 print('返回的是%s'%data.decode('gbk'))
11 phone.close() 六、基于UDP协议的socket
from socket import *
2 udp_server = socket(AF_INET,SOCK_DGRAM)
3 udp_server.bind(('127.0.0.1',8080)) #绑定
4 while True:#通讯循环
5 msg,client_addr= udp_server.recvfrom(1024)
6 print('收到的消息是:%s'%msg.decode('utf-8'))
7 udp_server.sendto(msg.upper(),client_addr)
8 udp_server.close()
# udp 无链接,所以不需要连接
2 from socket import *
3 udp_client = socket(AF_INET,SOCK_DGRAM)
4
5 while True:
6 msg = input('>>:').strip()
7 udp_client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))
8 res,sever_addr = udp_client.recvfrom(1024)
9 print('返回的结果是:%s'%res.decode('utf-8'))
10 udp_client.close()

基于UDP协议的socket的应用(模拟QQ聊天)

from socket import *
2 udp_server= socket(AF_INET,SOCK_DGRAM)
3 udp_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
4 udp_server.bind(('127.0.0.1',8080))
5 print('start running...')
6
7 while True:
8 qq_msg,addr = udp_server.recvfrom(1024)
9 print('来自[%s:%s]的一条消息:\033[44m%s\033[0m'%(addr[0],addr[1],qq_msg.decode('utf-8')))
10 back_msg = input('回复消息:>>').strip()
11 udp_server.sendto(back_msg.encode('utf-8'),addr)
12 udp_server.close()
from socket import *
2 udp_client = socket(AF_INET,SOCK_DGRAM)
3 qq_name_dic = {
4 '房得成':('127.0.0.1',8080),
5 '朱超':('127.0.0.1',8080),
6 '王雅玲':('127.0.0.1',8080),
7 '朱家伟':('127.0.0.1',8080)
8 }
9 while True:
10 qq_name = input('请输入聊天对象:>>').strip()
11 if qq_name not in qq_name_dic: continue
12 while True:
13 msg = input('请输入消息,回车发送:').strip()
14 if msg=='quit':break
15 if not msg or not qq_name or qq_name not in qq_name_dic:continue
16 udp_client.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
17 back_msg,addr = udp_client.recvfrom(1024)
18 print('来自[%s:%s]的一条消息:\033[41m%s\033[0m'%(addr[0],addr[1],back_msg.decode('utf-8')))
19 udp_client.close()

运行结果截图

五、subprocess子进程模块

import subprocess
2 #Popen方法是用来执行系统命令的,直接把结果打印到终端了
3 res =subprocess.Popen(r'dir',shell=True,
4 #r'dsfsdfr',shell=True,
5 # stdin= #标准输入(不常用)
6 stdout=subprocess.PIPE,#stdout 标准输出
7 stderr=subprocess.PIPE) #stderr 标准错误
8 # 拿到的是‘gbk’编码的结果,
9 # 这个命令可能有正确结果,也可能有错误结果
10 print(res.stdout.read().decode('gbk'))
11 print('========')
12 print(res.stdout.read().decode('gbk')) #说明只能读一次
13 print(res.stderr.read().decode('gbk')) #如果是错误的就会提示 六、struct模块
#该模块可以把一个类型,如数字,转成固定长度的bytes类型
2 import struct
3 # res = struct.pack('i',12345)
4 # print(res,len(res),type(res)) #长度是4
5
6 res2 = struct.pack('i',12345111)
7 print(res2,len(res2),type(res2)) #长度也是4
8
9 unpack_res =struct.unpack('i',res2)
10 print(unpack_res) #(12345111,)
11 # print(unpack_res[0]) #12345111

python中socket编程的更多相关文章

  1. Python中Socket编程server与client简单的合法性认证

    导入python自带的hmac模块对随机生成的位数32字节和自定义token进行加密处理 import osmsg = os.urandom(32)  #随机生成msgOut[4]: b"F ...

  2. Python中Socket编程(TCP、UDP)

    1. TCP协议下的如何解决粘包问题 TCP(transport control protocol 传输控制协议)  使用Nagle算法,将多次间隔较小且数据量小的数据,合并成大的数据块:接受端无法识 ...

  3. python之socket编程(一)

    socket之前我们先来熟悉回忆几个知识点. OSI七层模型 OSI(Open System Interconnection)参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标 ...

  4. 转:Python 的 Socket 编程教程

    这是用来快速学习 Python Socket 套接字编程的指南和教程.Python 的 Socket 编程跟 C 语言很像. Python 官方关于 Socket 的函数请看 http://docs. ...

  5. 操作系统底层原理与Python中socket解读

    目录 操作系统底层原理 网络通信原理 网络基础架构 局域网与交换机/网络常见术语 OSI七层协议 TCP/IP五层模型讲解 Python中Socket模块解读 TCP协议和UDP协议 操作系统底层原理 ...

  6. Python 3 socket 编程

    Python 3 socket编程 一 客户端/服务器架构 互联网中处处是C/S架构 1.C/S结构,即Client/Server(客户端/服务器)结构 2.在互联网中处处可见c/s架构 比如说浏览器 ...

  7. python中Socket的使用

    说明 前一段时间学习python网络编程,完成简单的通过python实现网络通信的功能.现在,将python中Socket 通信的基本实现过程做一个记录备份. Socket通信 python 中的so ...

  8. 最基础的Python的socket编程入门教程

    最基础的Python的socket编程入门教程 本文介绍使用Python进行Socket网络编程,假设读者已经具备了基本的网络编程知识和Python的基本语法知识,本文中的代码如果没有说明则都是运行在 ...

  9. Python:socket编程教程

    ocket是基于C/S架构的,也就是说进行socket网络编程,通常需要编写两个py文件,一个服务端,一个客户端. 首先,导入Python中的socket模块: import socket Pytho ...

随机推荐

  1. MVC系统学习8——AsyncController

    关于为什么使用异步Controller,这里不做备忘,三岁小孩都懂.主要的备忘是如何使用AsyncController. //这个action以Async结尾,并且返回值是void public vo ...

  2. 序列终结者(bzoj 1521)

    Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这 ...

  3. [转]MySQL5字符集支持及编码研究

    前言 在更新数据库时,有时会遇到这样的错误: Illegal mix of collations (gbk_chinese_ci,IMPLICIT) and (utf8_general_ci,COER ...

  4. 【BZOJ4583】购物(组合计数)

    题意:商店出售3种颜色的球,分别为红.绿.蓝. 城市里有n个商店,第i个商店在第First_i天开始营业,连续营业Red_i+Green_i+Blue_i天,每个商店每天只能出售一种颜色的球. 每天最 ...

  5. Linux下汇编语言学习笔记32 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  6. MSDN 同步部分 个人笔记

    (在知乎看到轮子哥说,掌握了MSDN上的并发部分 和 线程与进程部分就可以掌握所有语言的多线程编程,我在网上翻了一下并没有中文版,所以决定自己翻译一下...) 目录: 线程之间协同运行的方式有许多种, ...

  7. neutron trouble shooting - ip can not ping

    neutron创建了一个router后,显示列表如下: [root@controller01 keystone]# neutron router-port-list router +--------- ...

  8. C# 如何修改Form不能修改窗体大小

    把窗体的FormBorderSytle改一下就可以了,改成FixedSingle或者Fixed3D都可以        

  9. Trie树(Prefix Tree)介绍

    本文用尽量简洁的语言介绍一种树形数据结构 -- Trie树. 一.什么是Trie树 Trie树,又叫字典树.前缀树(Prefix Tree).单词查找树 或 键树,是一种多叉树结构.如下图: 上图是一 ...

  10. ppt五种经典字体组合

    在做ppt中常常为使用哪种字体而头疼,如今将ppt的经典字体附上.希望对大家有帮助 五种经典的字体组合 标题字体 正文字体 使用场合 方正综艺简体 微软雅黑 课题汇报.咨询报告.学术研讨等正式场合 方 ...