python学习_网络编程

1、基础概念

  架构:

    c/s:客户端/服务端架构,充分发挥客户端的性能;可以应用于计算机硬件(打印机,文件服务器)也可以应用于计算机软件;

    b/s:浏览器/客户端架构,统一了应用的接口;

  Python支持:AF_UNIX,AF_NETLINK,AF_TIPC,AF_INET;

  两台计算机之间的通信:网线,交换机;

  同一台计算机两个py文件之间的通信:socket/import/文件读写

  多个计算机之间的通信:交换机 (通信方式:广播,单播,组播)

  更多个计算机之间的通信:交换机 路由器;

  mac地址:物理地址,全球唯一,唯一的标示一台计算机;

  ip地址:逻辑地址

  端口:操作系统为本机的应用程序随机分配的一个端口(1-65535 0-1023不可用:预留给了系统)

  网段:一个局域网内ip地址的范围;

  子网掩码:用来计算网段的, 子网掩码 & ip地址-->判断是否在同一个网段;

  

  TCP: 面向连接的,可靠的,面向字节流形式的,TCP本质上就是只允许同一时间,一个服务器和一个客户端保持连接,type=SOCK_STREAM;面向连接的通信提供序列化的,可靠的和不重复的数据交付;

  UDP: 无连接的,不可靠的,面向数据报形式的,传输速度快,相对不可靠,允许一个服务器和多个客户端同时通信,type=SOCK_DGARM;与通信开始之前并不需要连接,消息是以整体发送的;

  OSI模型:

    物理层  光纤 集线器 网线 --传输电信号

    数据链路层  交换机 网卡 网桥 --arp协议

    网络层  路由器 三层交换机 --ip协议

    传输层  四层交换机 四层路由器 --tcp/udp协议

    应用层  http/https/ftp协议

  TCP协议的三次握手:

    一定是client发起请求,1、客户端发起请求连接服务器;2、服务器返回:接收到请求,并要求连接客户端;3、客户端回复:可以连接

  四次挥手:

    谁先发起断开连接的请求都可以,1、客户端发起断开连接的请求(表示次数我没有数据需要发送了,询问对方是否有数据要发送);2、服务端回复:我接收到你的请求了,3、服务端回复:我准备好断开连接了;4、客户单回复:收到信息,断开连接

    ACK:确认收到

    SYN: 请求连接的标示

    FIN: 请求断开的标志

  本地回环地址:127.0.0.1 本机地址,代表本地虚拟接口,只能被本机识别,不会被其他机器识别;

  

2、socket模块

   IPC:进程间通信

  是一个模块,一个套接字,是传输层和应用层之间的一个抽象层次

   TCP协议编码流程:

      粘包:可能发生粘包的问题(只有tcp可能会出现)

        原因:发送端在发送数据的时候,接收端不知道如何去接收,造成的一种数据混乱的现象;接收方不知道消息之间的界限, 不知道一次性提取多少字节造成的;

        在tcp协议中,有一个合包机制(nagle算法)将多次连续发送且间隔较小的数据,打包成一块数据进行传输,还有一个合包机制,在发送端,因为收到网卡MTU的限制,会将大的超过MTU限制的数据进行拆分,拆分成多个小的数据进行传输,当传输到目标主机的操作系统层的时候,会重新将多个小的数据合并成原本的数据;tcp粘包的拆包和合包机制发生在发送端;

        解决粘包问题:

          模块struct

            struct.pack(type, num) type:num的类型。num一个数字,把一个数字打包成一个四字节的bytes

            struct.unpack(type, r)解成原数字,结果是一个数组,原数字在下标为0de位置

        在upd协议中,不会发现粘包的现象,在udp协议中一次收发数据大小的限制是65535 - ip包头(20) - udp包头(8) = 65507, 在数据链路层,MTU一般限制在1500,1500-20-8 = 1472, sentto(num) num>65507会报错,1472~65507之间的数据会在数据链路层被拆包,而且udp本身不是一个可靠的协议,所以在拆包之后,多个小的数据包在网络传输中,如果丢失一个,此次数据传输失败,所以num<1472是比较理想的状态;

      服务端: 
        实例化对象

        绑定ip地址和端口号

        监听

        接收客户端的连接

        收法

        关闭

      客户端:

        实例化对象

        连接服务器

        收发

        关闭

      

# 服务端代码:
import socket
import time


sk = socket.socket()
sk.bind(('127.0.0.1', 8080))
sk.listen()

while 1:
    conn addr = sk.accept()
    while 1:
        msg = conn.recv(1024)
        print(msg.decode('utf-8'))
        if msg.decode('utf-8') == 'q':
            break
        print(conn,addr)
        msg_my = input(">>>")
        conn.send(msg_my.encode('utf-8')
        if msg_my == 'q':
            break
    conn.close()
    time.sleep(1)
    break;
sk.close()

# 客户端代码
import socket

sk = socket.socket()
sk.connect(('127.0.0.1', 8080))

while 1:
  msg = input(">>>")
  sk.send(msg.encode('utf-8'))
  if msg == 'q':
    break
  msg_s = sk.recv(1024)
  print(msg_s.decode('utf-8')
  if msg_s.decode('utf-8') == 'q':
    break
sk.close()

  s.connect():z主动发起tcp服务器连接,s.connect_ex() 拓展版本,不会抛出异常,而是以错误码显示问题

  s.listen(n):n是传入连接请求的最大数;

  服务端接收到客户端的消息是空白的,说明客户端已经断开连接

  udp协议及编码:

    type = SOCK_DGARM

    通信优势:可以和多个客户端通信

    服务端流程:

      实例化对象

      绑定ip和端口号

      收发数据

      关闭

    客户端流程:

      实例化对象

      收发数据

      关闭

# udp服务端实现
import socket

sk = socket.socket(type=socket.SCK_DGRAM)
sk.bind(('127.0.0.1', 9090)

while 1:
    msg_r, addr = sk.recvfrom(1024)
    name = msg_r.decode('utf-8').split(':')[0].strip()
    print(name)
    msg_s = input('>>>')
    sk,=.sendto(msg_s.encode('utf-8'), addr)

sk.close()

# udp客户端实现
import socket

sk = socket.socket(type=socket.SOCK_DGARM)

name = input(">>>")

while 1:
    msg_s = input(">>>")
    info = name + ":" + info
    sk.sendto(info.encode('utf-8'), ('127.0.0.1', 9090)
    msg_r, addr = sk.recvfrom(1024)
    print(msg_r.decode('utf-8')
sk.close()    

 

  socketServer:内置模块,主要是为了解决TCP协议中,服务器不能同时连接多个客户端的问题,是处在socket抽象层和应用层中的一层,比socket更贴近用户   

import socketServer

class Mysocket(socketserver.BaseRequestHandler):
    def handle(self):
            # 收发的逻辑
            msg = self.request.recv(1024).decode('utf-8')
            print(msg)
            self.request.send(msg.upper().encode('utf-8')

server = socketserver.TCPServer(('127.0.0.1', 8080), Mysocket) 固定写法
server.server_forever() 开启一个永久的服务
    

  socket更多使用方法:

    sk.setblocking(False-非阻塞状态/True-阻塞状态)  设置accept和recv两个方法的阻塞和非阻塞状态

    sk.settimeout(seconds) 设置等待超时时间

    conn.getpeername() 获取当前套接字的远端的地址

3、socketServer

  标准库中的一个高级模块,socketServer模块处理程序的默认行为是接受连接,获取请求,然后关闭连接

4、Twister

  是一个完整的事件驱动的网络框架,

4、面试:

  1、TCP协议为什么比UDP协议可靠?

      tcp是面向连接的,而udp是面向无连接的,tcp的通信过程中有一个ACK,(确认收到消息的一个标示);

  2、路由器和交换机的区别?

      交换机的主要功能是组织局域网,经过交换机内部处理解析信息之后,将信息以点对点,点对多的形式发送给固定端;路由器的主要功能:进行跨网段的数据传输,路由选择最佳路径;

5、网络协议

  1、ftp协议

    ftp协议底层只使用tcp而不适用udp

    python中的ftp模块 ftplib模块

  2、电子邮件(SMTP--简单邮件传输协议)

    RFC规定,邮件可以没有正文,但一定要有标题,SMTP端口25,第一个用来下载邮件的协议POP(邮局协议),其他的有因特网消息访问协议(IMAP)--更适合多邮件客户端  

posted @ 2019-08-01 10:02  Laura&  阅读(131)  评论(0)    收藏  举报