zoukankan      html  css  js  c++  java
  • 网络编程知识点剖析

    网络编程知识点剖析

    . C/S 架构: Client / Server  客户端 / 服务端

        B/S 架构: Browser / Server  前端 / 服务端

     

    .网络编程通信流程.

      网卡   mac地址   IP地址   子网掩码   网关   DNS服务器  (进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器。)  

      DHCP (自动分配IP)    NAT (Network Address Translation,网络地址转换)  端口   路由器

         交换机   集线器   广播 单播 广播风暴   arp协议(地址解析协议)    路由协议

     

    .网络通信协议

     1. osi七层:            tcp ip 五层:

          应用层              应用层  

          表示层              传输层

          会话层              网路层

          传输层              数据链路层

          网络层              物理层

          数据链路层

          物理层

      2. TCPIP 协议存在 传输层   

        Tcp   : 面向连接,消息可靠,效率相对差,面向流的消息格式,无消息保护边界    

        Udp  : 面向无连接,消息不可靠,效率高,面向包的消息格式,有消息保护边界

        tcp三次握手:1.(client) > [SYN包 ]->(server)   请求建立连接

              2.(client) < [SYN/ACK] < (server)  severs收到syn 发送[SYN/ACK]确认包

              3.(client)> [ACK] >(server)  client收到[SYN/ACK] 在发一个[ACK]确认包

        tcp四次挥手:1.(client) > [ACK/FIN] >(server) 发送包 请求关闭

              2.(client) < [ACK] <(server)  收到包  同意关闭

              3.(client) <[ACK/FIN] <(server) 收到包   是否收到 同意关闭 消息 

              4.(client) > [ACK/FIN] >(server)  发送包  收到过程2的消息,

    四.socket

      1. 服务端与客户端 手法消息 基本结构

    server>>>>>>>>>>>>>>>>>
    
    import socket
    sk = socket.socket()
    sk.bind(('127.0.0.1',8898))  #把地址绑定到套接字
    sk.listen()          #监听链接
    conn,addr = sk.accept() #接受客户端链接
    ret = conn.recv(1024)  #接收客户端信息
    print(ret)       #打印客户端信息
    conn.send(b'hi')        #向客户端发送信息
    conn.close()       #关闭客户端套接字
    sk.close()        #关闭服务器套接字(可选)
    
    client>>>>>>>>>>>>>>>>
    import socket
    sk = socket.socket()           # 创建客户套接字
    sk.connect(('127.0.0.1',8898))    # 尝试连接服务器
    sk.send(b'hello!')
    ret = sk.recv(1024)         # 对话(发送/接收)
    print(ret)
    sk.close()            # 关闭客户套接字
    tcp 服务端和客户端通信 基本代码
    server>>>>>>>>>>>>>>>>>>>>>>>>
    
    import socket
    udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
    udp_sk.bind(('127.0.0.1',9000))        #绑定服务器套接字
    msg,addr = udp_sk.recvfrom(1024)
    print(msg)
    udp_sk.sendto(b'hi',addr)                 # 对话(接收与发送)
    udp_sk.close()                         # 关闭服务器套接字
    
    client>>>>>>>>>>>>>>>>>>>>>>>>
    
    import socket
    ip_port=('127.0.0.1',9000)
    udp_sk=socket.socket(type=socket.SOCK_DGRAM)
    udp_sk.sendto(b'hello',ip_port)
    back_msg,addr=udp_sk.recvfrom(1024)
    print(back_msg.decode('utf-8'),addr)
    udp

      2.缓冲区

         作用:  提高效率,将发送或者接受信息的过程与网络传输隔离开,解耦

        特性:  1.I/O缓冲区在每个TCP套接字中单独存在;
             2.I/O缓冲区在创建套接字时自动生成;
             3.即使关闭套接字也会继续传送输出缓冲区中遗留的数据;
             4.关闭套接字将丢失输入缓冲区中的数据。
        大小:  一般默认为 8K, 可以通过 getsockopt() 函数获取

      3.粘包

        TCP会粘包、UDP永远不会粘包

        粘包的两种现象: 

        1.连续发送小包并且间隔时间很短,就会发送两个消息合并在一起的情况,被一次接受了,(Nagel 优化算法导致的,            避免连续发送小包,影响传输xiaol)

        2.一次发送数据过大,对方一次未接受完导致下次接受的时候,连同第一次剩下的消息,一同接受了,导致粘包.

        解决粘包的方案: 

          原因是因为双方不知道对方发送的消息长度

        1.发送消息之前先发送消息的长度,然后收到对方的确认信息后再发送消息.

        2.通过struct模块,自定义包头,将消息长度打包成4个字节长度的信息,连同你要发送的数据,一起发送过去

          打包:pack('i',长度) 长度是个整数

          解包:unpack('i',接受的那4个字节),得到的是元祖

        Sendall(): 循环的send直到数据发送完毕.

        Socketsserver(): 实现tcp协议下,一个服务端可以同时和多个客户端进行通信.

    import socket,struct,json
    import subprocess
    phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    
    phone.bind(('127.0.0.1',8080))
    phone.listen(5)
    
    while True:
        conn,addr=phone.accept()
        while True:
            cmd=conn.recv(1024)
            if not cmd:break
            print('cmd: %s' %cmd)
    
            res=subprocess.Popen(cmd.decode('utf-8'),
                                 shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
            err=res.stderr.read()
            print(err)
            if err:
                back_msg=err
            else:
                back_msg=res.stdout.read()
    
            headers={'data_size':len(back_msg)}
            head_json=json.dumps(headers)
            head_json_bytes=bytes(head_json,encoding='utf-8')
    
            conn.send(struct.pack('i',len(head_json_bytes))) #先发报头的长度
            conn.send(head_json_bytes) #再发报头
            conn.sendall(back_msg) #在发真实的内容
    
        conn.close()
    解决粘包方案一 server
    import socket
    import struct,json
    client= socket.socket()
    client.connect(("127.0.0.1",8080))
    
    while True:
        cmd=input(">>: ")
        if not cmd:continue
        client.send(bytes(cmd,encoding='utf-8'))
    
        head=client.recv(4)
        head_json_len=struct.unpack('i',head)[0]
        head_json=json.loads(client.recv(head_json_len).decode('utf-8'))
        data_len=head_json['data_size']
    
        recv_size=0
        recv_data=b''
        while recv_size < data_len:
            recv_data = client.recv(1024) + recv_data
            recv_size = len(recv_data) + recv_size
    
        print(recv_data.decode('gbk'))
    解决粘包解决方案一 client
    import socketserver
    class Myserver(socketserver.BaseRequestHandler):
        def handle(self):
            self.data = self.request.recv(1024).strip()
            print("{} wrote:".format(self.client_address[0]))
            print(self.data)
            self.request.sendall(self.data.upper())
    
    if __name__ == "__main__":
        HOST, PORT = "127.0.0.1", 9999
    
        # 设置allow_reuse_address允许服务器重用地址
        socketserver.TCPServer.allow_reuse_address = True
        # 创建一个server, 将服务地址绑定到127.0.0.1:9999
        #server = socketserver.TCPServer((HOST, PORT),Myserver)
        server = socketserver.ThreadingTCPServer((HOST, PORT),Myserver)
        # 让server永远运行下去,除非强制停止程序
        server.serve_forever()
    tcp_server_sockserver
    import socket
    
    HOST, PORT = "127.0.0.1", 9999
    data = "hello"
    
    # 创建一个socket链接,SOCK_STREAM代表使用TCP协议
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect((HOST, PORT))          # 链接到客户端
        sock.sendall(bytes(data + "
    ", "utf-8")) # 向服务端发送数据
        received = str(sock.recv(1024), "utf-8")# 从服务端接收数据
    
    print("Sent:     {}".format(data))
    print("Received: {}".format(received))
    tcp_client_socketserver

      

  • 相关阅读:
    第一次站立会议
    电梯会议的相关视频
    软件需求分析--NABCD
    05需求工程软件建模与分析阅读笔记之五
    04需求工程软件建模与分析阅读笔记之四
    03需求工程软件建模与分析阅读笔记之三
    02需求工程软件建模与分析阅读笔记之二
    jsp+javabean+servlet实现简单的登录
    账户分析系统需求分析
    01需求工程软件建模与分析阅读笔记之一
  • 原文地址:https://www.cnblogs.com/konghui/p/9900738.html
Copyright © 2011-2022 走看看