重点回顾:

(重点)粘包 :  就是因为接收端不知道如何接收数据,造成接收数据的混乱的问题
只发生在tcp协议上. 因为tcp协议的特点是面向数据流形式的传输
粘包的发生主要是因为tcp协议有两个机制: 合包机制(nagle算法),拆包机制 subprocess 模块 有一个方法可以执行系统命令 Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) struct 模块 有一个方法可以将21.3E以内的数据,打包成4个长度的bytes
r = struct.pack('i',num)
struct.unpack('i',r) (重点)架构: C/S架构 B/S架构(优点:统一了应用的接口) 多台电脑通信 : 交换机+路由器 mac地址: 物理地址,全球唯一 身份证号
ip地址 : 虚拟地址,四位点分十进制 学号 (重点)如何判断两台主机是否在同一个局域网?
ip地址 & 子网掩码 = 网段 (重点)arp协议: 通过目标ip地址,获取目标mac地址 端口:操作系统给予,通过端口号,可以确定某一个应用程序
(重点)ip+端口:唯一确定某一个主机上的某一个应用程序
回环地址:127.0.0.1 osi五层模型:
应用层 py文件,应用
传输层 tcp/udp协议
网络层 ip协议
数据链路层 arp协议,网卡
物理层 网线,集线器,光纤 (重点)tcp协议:安全,可靠,面向连接,面向数据流形式的传输
三次握手:
(面试回答)
首先,必须先由客户端发起连接的请求
接下来,服务器接收到请求之后,回复给客户端两个标识,一个syn表示
服务器接收到请求,一个ack表示服务器在做准备工作,两个标识一起
回复给客户端
最后,客户端接收到服务器的回复,客户端准备连接的所有资源,开始进行连接
发送给服务器一个ack表示客户端的连接准备工作已经完成
(此时表示客户端和服务器可以相互连接了)
如果面试官问你,哪句代码体现了三次握手?
回答: 服务器端的accept,客户端connect 四次挥手:
(面试回答)
(1)首先由连接双方任意一方发起断开连接的请求,发起方发送的请求表示
是我没有数据要继续发送了,可以断开连接了,但是你如果还有数据可以继续向我发送数据.
(2)接收方回复给发起方,表示接到了发起放的断开请求,开始着手准备断开事宜
(3)接收方准备完成后,给发起方发送一个标识,表示接受方没有数据继续发送了
可以断开连接了
(4)发起方接收到消息后,准备断开连接,回收资源
如果面试官问你,哪句代码体现了四次挥手?
回答: close() (重点)udp协议:快. 不安全,不可靠,不面向连接,面向数据包形式的传输

官方文档对socket模块下的socket.send()和socket.sendall()解释如下:

socket.send(string[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Returns the number of bytes sent. Applications are responsible for checking that all data has been sent; if only some of the data was transmitted, the application needs to attempt delivery of the remaining data. send()的返回值是发送的字节数量,这个数量值可能小于要发送的string的字节数,也就是说可能无法发送string中所有的数据。如果有错误则会抛出异常。 – socket.sendall(string[, flags])
Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from string until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent. 尝试发送string的所有数据,成功则返回None,失败则抛出异常。 故,下面两段代码是等价的: #sock.sendall('Hello world\n') #buffer = 'Hello world\n'
#while buffer:
# bytes = sock.send(buffer)
# buffer = buffer[bytes:] send和sendall方法

send与sendall官方文档

 ----------socket的更多方法介绍---------------

服务端套接字函数
s.bind() 绑定(主机,端口号)到套接字
s.listen() 开始TCP监听
s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来 客户端套接字函数
s.connect() 主动初始化TCP服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 公共用途的套接字函数
s.recv() 接收TCP数据
s.send() 发送TCP数据
s.sendall() 发送TCP数据
s.recvfrom() 接收UDP数据
s.sendto() 发送UDP数据
s.getpeername() 连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt() 返回指定套接字的参数
s.setsockopt() 设置指定套接字的参数
s.close() 关闭套接字 面向锁的套接字方法
s.setblocking() 设置套接字的阻塞与非阻塞模式
s.settimeout() 设置阻塞套接字操作的超时时间
s.gettimeout() 得到阻塞套接字操作的超时时间 面向文件的套接字的函数
s.fileno() 套接字的文件描述符
s.makefile() 创建一个与该套接字相关的文件

更多方法

sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 允许一个端口号重用的解决方法,同时开启多个服务端.
(重点)setblocking(True)  阻塞
   setblocking(False) 非阻塞
   settimeout(int)    针对阻塞状态,设置一个延时等待
   gettimeout()       获得延时的时间

验证客户端链接的合法性

如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用hmac+加盐的方式来实现

# 此代码用真实的随机字符串
# import socket
# import hashlib
# import os
# sk = socket.socket()
# sk.bind(('127.0.0.1',9090))
# sk.listen()
# conn,addr = sk.accept()
# key = '天王盖地虎'# 这个是固定盐
# ch = os.urandom(10)
# conn.send(ch)# 把随机字符串发给client
# md5_obj = hashlib.md5(key.encode('utf-8'))
# md5_obj.update(ch)
# re = md5_obj.hexdigest()
# # 固定的用盐的加密方式
# client_re = conn.recv(1024).decode('utf-8')# 接收client端加密后的结果
#
# if re == client_re:
# print('你好机油!')
# '''收发数据的逻辑'''
# else:
# print('你根本不是老司机')
# conn.close()
# sk.close()

服务端

# import socket
# import hashlib
# sk = socket.socket()
# sk.connect(('127.0.0.1',9090))
#
# key = '天王盖地虎'
# ch = sk.recv(1024)
# md5_obj = hashlib.md5(key.encode('utf-8'))
# md5_obj.update(ch)
# re = md5_obj.hexdigest()
# sk.send(re.encode('utf-8'))
#
# sk.close()

客户端

用hmac验证:

# 调用hmac模块中的加密方法
import socket
import hashlib
import os
import hmac
sk = socket.socket()
sk.bind(('127.0.0.1',9090))
sk.listen()
conn,addr = sk.accept()
key = '天王盖地虎'# 这个是固定盐
ch = os.urandom(10)
conn.send(ch)# 把随机字符串发给client
obj = hmac.new(key.encode('utf-8'),ch)
re = obj.digest()
# 固定的用盐的加密方式
client_re = conn.recv(1024)# 接收client端加密后的结果 if re == client_re:
print('你好机油!')
'''收发数据的逻辑'''
else:
print('你根本不是老司机')
conn.close()
sk.close()

服务端

# 此代码用hmac模块实现机密
import socket
import hashlib
import hmac
sk = socket.socket()
sk.connect(('127.0.0.1',9090)) key = '天王盖地虎'
ch = sk.recv(1024)
obj = hmac.new(key.encode('utf-8'),ch)
re = obj.digest()
sk.send(re) sk.close()

客户端

---------------socketserver-----------------

# import socketserver
# #sk conn 等效于 self.requset.
# class Myserver(socketserver.BaseRequestHandler):
# def handle(self):
# # print(123)
# # self.request.send()
# print(self.request.recv(1024).decode('utf-8'))
#
# server = socketserver.TCPServer(('192.168.19.200',9090),Myserver)
#
# server.serve_forever() # ========================================
import socketserver
#sk conn
import json
import hashlib
class Myserver(socketserver.BaseRequestHandler):
def handle(self):
while 1:
dic_str = self.request.recv(1024).decode('utf-8')# 接收到序列化的字典
dic = json.loads(dic_str)# 反序列化字典,字典中有用户名和密码
# 用户名当盐 加上密码去做md5
with open('info',encoding='utf-8') as f:
for user_info in f:# 旭哥 | 7d79a61dd0bd94a3df2f765ac12fe492
username,pawd = user_info.split('|')
if username.strip() == dic['username']:# 先去对比用户名正确与否
'''如果用户名存在的情况下
加密方式 : 用户名当盐,对密码加密'''
md5_obj = hashlib.md5(dic['username'].encode('utf-8'))
md5_obj.update(dic['passwd'].encode('utf-8'))
re = md5_obj.hexdigest()
if re == pawd.strip():# 拿加密完的密码密文对比文件中密码的密文
self.request.send(b'success!')
'''通信的逻辑'''
else:
'''失败,返回给客户端信息.....'''
self.request.send(b'failed!')
break
else:
'''对应for 如果用户名不存在'''
print('用户不存在!') server = socketserver.TCPServer(('127.0.0.1',9090),Myserver)# 绑定一个服务
server.serve_forever()# 永久性开启服务

服务端

import socket
import time
import json
sk = socket.socket()
sk.connect(('127.0.0.1',9090))
dic = {'username':None,'passwd':None}
while 1:
username = input('用户名>>>')
passwd = input('密码>>>')
dic['username'] = username
dic['passwd'] = passwd
dic_str = json.dumps(dic)
sk.send(dic_str.encode('utf-8'))
print(sk.recv(1024)) sk.close()

客户端

handle方法内写收发逻辑,   conn  ==   self.requset.

python 网络编程(socketserver,阻塞,其他方法)的更多相关文章

  1. python网络编程socketserver模块(实现TCP客户端/服务器)

    摘录python核心编程 socketserver(python3.x版本重新命名)是标准库中的网络编程的高级模块.通过将创建网络客户端和服务器所必须的代码封装起来,简化了模板,为你提供了各种各样的类 ...

  2. python网络编程——SocketServer/Twisted/paramiko模块

    在之前博客C/S架构的网络编程中,IO多路复用是将多个IO操作复用到1个服务端进程中进行处理,即无论有多少个客户端进行连接请求,服务端始终只有1个进程对客户端进行响应,这样的好处是节省了系统开销(se ...

  3. python网络编程-socketserver

    一:socketserver简化了网络服务器的编写. 它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer. 这4个类是同步进行处 ...

  4. python网络编程--socketserver 和 ftp功能简单说明

    1. socketserver 我们之前写的tcp协议的socket是不是一次只能和一个客户端通信,如果用socketserver可以实现和多个客户端通信.它是在socket的基础上进行了一层封装,也 ...

  5. python网络编程-socketserver模块

    使用socketserver 老规矩,先引入import socketserver 必须创建一个类,且继承socketserver.BaseRequestHandler 这个类中必须重写handle( ...

  6. Python网络编程-IO阻塞与非阻塞及多路复用

    前言 问题:普通套接字实现的服务端的缺陷 一次只能服务一个客户端!                         accept阻塞! 在没有新的套接字来之前,不能处理已经建立连接的套接字的请求 re ...

  7. python网络编程05 /TCP阻塞机制

    python网络编程05 /TCP阻塞机制 目录 python网络编程05 /TCP阻塞机制 1.什么是拥塞控制 2.拥塞控制要考虑的因素 3.拥塞控制的方法: 1.慢开始和拥塞避免 2.快重传和快恢 ...

  8. Python网络编程03 /缓存区、基于TCP的socket循环通信、执行远程命令、socketserver通信

    Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命令.socketserver通信 目录 Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命 ...

  9. python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)

    python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...

随机推荐

  1. logistic regression svm hinge loss

    二类分类器svm 的loss function 是 hinge loss:L(y)=max(0,1-t*y),t=+1 or -1,是标签属性. 对线性svm,y=w*x+b,其中w为权重,b为偏置项 ...

  2. c语言描述的二分插入排序法

    #include<stdio.h> #include<stdlib.h> //二分插入排序法 void BinsertSort(int a[],int n){ int low, ...

  3. JWT如何在Spring Cloud微服务系统中在服务相互调时传递

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78676036 本文出自方志朋的博客 在微服务系统中,为了保证微服务系统的安全,常常使用jw ...

  4. idea常用技巧

    1.如何设置,使IntelliJ IDEA智能提示忽略大小写 打开设置(CTRL+ALT+S)搜索editor,找到“Code Completion”->点击Case sensitive com ...

  5. Spring框架中的IOC?

    Spring中的org.springframework.beans包和org.SpringframeWork.context包构成了Spring框架IOC容器的基础.BeanFactory接口提供了一 ...

  6. 编写可维护的JavaScript之编程风格

    在团队中只有每个人的编程风格一致,大家才能方便的互相看懂和维护对方的代码. 1. 层级缩进 对于层级缩进目前有两种主张:1)使用制表符这种方法有两种好处,第一,制表符和缩进层级之间是一一对应关系,符合 ...

  7. 『ACM C++』HDU杭电OJ | 1415 - Jugs (灌水定理引申)

    今天总算开学了,当了班长就是麻烦,明明自己没买书却要带着一波人去领书,那能怎么办呢,只能说我善人心肠哈哈哈,不过我脑子里突然浮起一个念头,大二还要不要继续当这个班委呢,既然已经体验过就可以适当放下了吧 ...

  8. python 之函数

    一 函数的定义:对功能和动作的封装和定义.二 函数的格式:def 函数名(形参列表): 函数名就是变量名:规则就是变量的规则 函数体(return) ret = 函数名(实参列表)三 函数的返回值:函 ...

  9. Linux下安装google拼音输入法

    首先安装fcitx,前几天看了很多在ubuntu上能够使用的输入法,有人推荐是搜狗输入法,毕竟是国产嘛,但是会有意外发生,比如说安装之后会产生输入的字符乱码,是一堆看不懂的东西,我就是因为遇到了,然后 ...

  10. maven-坐标与依赖

    1.坐标-找到项目依赖的重要依据 <groupId>cmbc.com.cn</groupId> <artifactId>myapp</artifactId&g ...