zoukankan      html  css  js  c++  java
  • 网络编程

    网络编程自我感觉还是很重要的一部分

    网络基础

    C/S架构 client/server
    B/S架构 server/browser
     两者的关系?
     B/S架构是C/S架构的一种

    计算机与计算机之间是如何通信的?

    两台计算机之间的通信

    网卡、网线

    网卡:提供网线的接口,通过网卡找到计算机,一个网卡拥有全球唯一的mac地址

    同一个局域网中多台计算机之间的通信

    网卡,网线,交换机

    交换机:一个中心节点,所有的网线连接到交换机上

    计算机1寻找计算机2并发消息的过程:

      计算机1发送消息到交换机,交换机把这个信息广播给局域网中所有计算机,计算机2收到消息与自己的mac地址比对,确认是发给自己的消息之后,回复消息给交换机,交换机发消息到计算机1

    不同局域网中多台计算机之间的通信

    网卡,网线,交换机,路由器

    路由器:连接多个交换机

    广播:计算机1要和计算机2通信,告诉交换机要找计算机2,交换机会告诉所有的计算机要找计算机2
    广播风暴:所有的计算机同时去找,同一台计算机会接收到很多与自己不相关的信息,从而造成网络拥堵
    单播:只有计算机2会回复消息给交换机,交换机发送给计算机1

    网关:不同的局域网中的计算机之间通信,同一个局域网的默认网关相同
    子网掩码:ip地址和子网掩码按位与 (计算出来局域网的网段,同一个网段只有最后一位不同,前三位都相同)来判断是否在同一局域网
    按位与:1|1=1,1|0=1,0|0=0

    ip地址

    4个点分十进制(4个八位二进制数)范围:0-255

    作用:
    通过ip地址可以找到对应的mac地址 根据arp协议
    127.0.0.1:本地回环地址,本地中的两个程序通信

    ip协议

    IPV4:0.0.0.0-255.255.255.255
    IPV6:0.0.0.0.0.0-255.255.255.255.255.255
    作用:1.为一台计算机分配ip地址
       2.计算计算机的网段
    如果想让别人能访问到自己的计算机中的程序,必须有一个已经在公网中注册的ip地址

    端口

    计算机里边的每一个需要联网的程序都有一个端口

    qq聊天时,对方不仅需要你的ip地址,还需要qq程序的端口号
    端口的范围:0-25535
    自己开端口:开8000后的端口

    互联网协议

    每层的工作

      应用层   程序,要发送的数据包
      传输层   选择通信协议,给要发送的数据加上协议
      网络层   给要发送的数据加上ip信息
      数据链路层    通过arp协议得到mac地址,给要发送的数据加上mac地址
      物理层   两个计算机链接
    每层用到的协议:

      应用层   http协议,SMTP协议,ftp协议
      传输层   TCP/UDP协议
      网络层   ip协议
      数据链路层   ARP协议
      物理层
    每层常见物理设备:

      应用层
      传输层   四层交换机,四层路由器
      网络层   路由器,三层交换机(带路由功能)
      数据链路层    网桥,交换机,网卡
      物理层   中继器,双绞线,集线器

    TCP协议/UDP协议

    TCP协议:可靠的,建立链接的
      全双工通信:双方可以互相收发信息
      三次握手:一定是client先请求发送--server端接受请求并且请求发送--client端接收请求 通道连接成功
      四次挥手:client/server请求断开连接--server/client同意断开--server/client请求断开连接--client/server同意断开
    UDP协议:
      不建立链接的,不可靠的

    网络编程

    使用socket编程来进行进程间的通讯

    基于TCP协议的socket编程

    TCP服务端:创建套接字 (socket)--绑定端口 (bind)--倾听客户请求(listen)--接受客户端连接(accept)--接受、发送(recv、send)--关闭套接字(closesocket)
    TCP客户端:创建套接字(socket)--链接服务器(connect)--发送,接受(send、recv)--关闭套接字(closesocket)

    import socket
    soc = socket.socket()  #手机开机
    soc.bind(('localhost',9999))    #启动SIM卡
    soc.listen()    #等待别人打电话
    connect,addr = soc.accept()     #拿到通话连接,别人的电话号
    recv = connect.recv(1024)       #听别人讲话
    send = connect.send(b'hello')       #对别人讲话
    print(str(recv))
    connect.close()     #挂断电话
    soc.close()     #关机
    TCP_Server
    import socket
    sock = socket.socket()      #手机开机
    sock.connect(('localhost',9999))       #给别人打电话
    sock.send(b'jcc')       #对别人讲话
    rec = sock.recv(1024)       #听别人讲话
    print(str(rec))
    sock.close()    #关机
    TCP_Client

    基于UDP协议的socket编程

    import socket
    udpsk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字  DGRAM:datagram  基于udp传输的数据包
    udpsk.bind(('localhost',8888))      #绑定指定服务器
    while 1:
        msg,addr = udpsk.recvfrom(1024)     #接受消息
        print(msg.decode('utf-8'))
        if msg.decode('utf-8')=='bye':break
        inp = input('>>>')
        udpsk.sendto(bytes(inp,encoding='utf-8'),addr)  #发送消息
    udpsk.close()  #关闭套接字
    UDP_Server
    import socket
    udpsk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字  DGRAM:datagram  基于udp传输的数据包
    udpsk.bind(('localhost',8888))      #绑定指定服务器
    while 1:
        msg,addr = udpsk.recvfrom(1024)     #接受消息
        print(msg.decode('utf-8'))
        if msg.decode('utf-8')=='bye':break
        inp = input('>>>')
        udpsk.sendto(bytes(inp,encoding='utf-8'),addr)  #发送消息
    udpsk.close()  #关闭套接字
    UDP_Client

    数据传输过程中的黏包现象

    现象:
        接受和发送不匹配
        
        基于UDP协议的传输不会出现黏包现象,一次接收不完的信息会被丢掉
        基于TCP协议的传输会出现黏包现象,但是不丢包
        基于UDP协议的传输会限制数据包的大小,超过的信息被丢掉
        基于TCP协议的传输不会限制数据包的大小
    产生黏包的原因:
        TCP协议是面向流的,无边界的
        TCP协议有一种拆包机制,当发送的数据包大于网关的mtu(网络上传输的最大数据包),该数据包就会被拆开,分批发送
     
         Nagle算法:优化传输速度(将多次间隔较小且数据量小的数据合并成一个大的数据块,封包)导致黏包现象
        
        黏包出现的最终原因:不知道要接受的数据有多大

    解决黏包方式1

    先发送数据包的长度,根据长度接受数据(缺点:多了一次客户服务器之间的交互)

    import socket
    sock = socket.socket()
    sock.bind(('127.0.0.1',9991))
    sock.listen()
    conn,addr = sock.accept()
    while 1:
        cmd = input('>>>')
        conn.send(cmd.encode('gbk'))
    
        len1 = conn.recv(1024)  #先接受长度
    
        recv = conn.recv(int(len1.decode('gbk')))   #根据长度接受数据包
        print('std:'+recv.decode('gbk'))
    解决黏包Server
    import socket
    import subprocess
    sock = socket.socket()
    sock.connect(('127.0.0.1',9991))
    while 1:
        cmd = sock.recv(1024)
        #执行计算机命令subprocess
        sb = subprocess.Popen(cmd.decode('gbk'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        stdout = sb.stdout.read()
        stderr = sb.stderr.read()
        print('stdout'+str(len(stdout)))
        print('stderr' + str(len(stderr)))
    
        sock.send(str(len(stdout)+len(stderr)).encode('gbk'))   #发送长度
    
        sock.send(stdout)   #发送消息
        sock.send(stderr)
    解决黏包Client

    借助struct模块解决黏包

    struct模块

    import struct
    p = struct.pack('i',20)#int转bytes
    print(p)
    num = b'1223'
    unp = struct.unpack('i',num)[0]#bytes转int
    print(unp)
    struct介绍

    socketServer

    import socketserver
    class Myserver(socketserver.BaseRequestHandler):    #继承BaseRequestHandler
        def handle(self):               #重写handle函数
            self.data = self.request.recv(1024)     #self.request相当与conn,接受信息
            print(self.client_address[0])
            print(self.data.decode('utf-8'))
            self.request.sendall(self.data) #发送消息
    
    if __name__ == '__main__':
        host,port = '127.0.0.1',9999
        socketserver.TCPServer.allow_reuse_address = True   # 设置allow_reuse_address允许服务器重用地址
        server = socketserver.TCPServer((host,port),Myserver)     # 创建一个server, 将服务地址绑定到127.0.0.1:9999
        server.serve_forever()  #程序一直运行
    socketserver
  • 相关阅读:
    python ratelimit使用
    团队怎样去做技术规划
    分词语义提取工具
    今日头条推荐系统
    要选择做有价值的事情
    总结与规划
    性能使用到极限
    流量运营
    Stanford CoreNLP使用需要注意的一点
    七年总结
  • 原文地址:https://www.cnblogs.com/jiangchengcheng/p/9669702.html
Copyright © 2011-2022 走看看