打赏

Python网络和Web(2)——socket

客户端服务器架构  C/S架构

1、硬件C/S架构(打印机)

2、软件C/S架构(web服务)

OSI七层或五层

完整计算机系统 由 硬件、操作系统、应用软件。计算机之间通信需要一堆协议组成,协议就是标准

1、物理层   光缆、网线

2、数据链路层   Ethernet 协议以太网协议,基于广播方式来找Mac地址等,是局域网内查找的协议

3、网络层    IP协议,查找IP,加一层网络协议,找网关,根据掩码等计算目标IP地址

4、传输层      端口号来标识   TCP  UDP协议

5、应用层     应用软件

传输层   与  应用层    中间是 socket  抽象层  ,应用软件的数据要发送出去,需要封包到传输层 ,socket是一组接口,tcp/ip算法处理的太复杂,用socket接口来使用的话避免了复杂的编程,相当于把这两个过程打包了,或者可以理解为IP和端口号打包在一起传

socket套接字

AF_INET目前是基于这个网络类型的套接字家族

 tcp协议的套接字工作流程

 绑定的情况下,会监听端口号,程序停止后,端口不一定清楚,程序再启动,会被占用,MAC系统常见

AF_INET  地址家族         TCP

 网络传输的数据都是字节二进制的

服务端服务程序简易如下:

import socket

ip_port=('127.0.0.1',8080)
tcp_server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_server.bind(ip_port)   #bind需要绑定的是个元组
tcp_server.listen(5)  #最大链接数

print('begin')
conn,addr=tcp_server.accept()    #连接客户端

print('双向连接是',conn)
print('客户端地址',addr)

while True:
    data=conn.recv(1024)
    print('客户端发来的消息是',data.decode('utf-8'))
    conn.send(data.upper())

conn.close()

tcp_server.close()

简单的客户端程序:

from socket import *

client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))

while True:
    client.send('hello'.encode('utf-8'))
    print('客户端发消息了')
    data=client.recv(1024)
    print('收到服务端消息',data.decode('utf-8'))

client.close()

客户端在断的时候服务端也会断,并报错,accept一次就是开一个连接,属于阻断的服务,只服务于一个客户端,想要循环多的提供服务就是在accept前面加 while True

要注意MAC LINUX系统下可能不会报异常 需要判断data是不是空

服务端客户端收发消息原理:

内核态内存,会一直在内存中,而软件启动会临时加载到内存中,叫用户态内存

socket程序 相当于软件,会通过操作系统才能操纵底层的网卡收发数据

而socket是用户态内存,操作系统是内核态内存,实际上 recv   send 都是和操作系统来通信,这样客户端如果输入的是空,那么send发到自己缓存发空给操作系统,操作系统内核态中是没内容的,自然也什么都没发,所以卡住了,避免为空则加一句if not mag:continue

 

队列  先进先出   堆栈  先进后出    

当收的不全的时候比如1024不够的情况下,后面的消息会排队,先进先出的队列

SYN洪水攻击,是因为有大量的连接3次握手后就跑了,来不及4次挥手,4次挥手会遗留状态就挂在那,端口会出现大量的timewait状态

 UDP套接字

没有了listen   和accept

recvfrom    收    sendto 发    区别

TCP  UDP都是从缓冲区拿数据,UDP可以接收空??对么?留个悬念

recv是TCP在自己缓冲区为空是会阻塞

recvfrom是UDP在自己缓冲区为空就会收一个空

udp没有链接这一说,就是并发的,收到就回,不需要链接

 

subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE)   执行dir命令,程序之间通过管道来通信stdout   就是把控制的命令装管道里传给对方,然后让对方读的时候 执行

 粘包现象

是由于buffer_size缓存不够造成的,只有tcp会有粘包现象,udp是不会粘包的,因为他就管发,只收一次,丢不丢数据不管,发的多收的少的话就都丢掉了不会有粘包现象,而TCP是基于链接的传输非常可靠,收不完下一个继续收

TCP是面向流的协议,容易粘包, TCP有优化算法Nagle算法,可以将多次的时间间隔较小的数据量小的数据,合并成一个大数据来传输,这样当客户端连续多次发送小数据的时候,接收端可能会出现一起接收的现象

UDP是面向消息的协议,一条消息就是一个数据报文,所以提取必须以一个消息为单位来提取,发送的消息有消息头来定义保护数据的边界,长度

粘包的两种情况:1、发的少 接收的多 比如发5、5、5 收1024 会一次都接收到   2、发的多  接收的少  比如发1024 收5

UDP则是一个recvfrom 对应一个 sendto 无论收发的大小。    而TCP由于有优化算法所以不是一一对应的

解决方法:

low版的解决方法,用消息头包含数据的长度,然后一步步收

取长度用struct.pack()模块来取长度可以提高程序的效率

 

functiontools.partial偏函数  可以固定参数

 

posted on 2019-07-29 17:32  大有哥  阅读(170)  评论(0)    收藏  举报

导航