网络编程知识点剖析

网络编程知识点剖析前端

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

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

 

.网络编程通讯流程.编程

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

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

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

 

.网络通讯协议架构

 1. osi七层:            tcp\ ip 五层:dom

      应用层              应用层  socket

      表示层              传输层

      会话层              网路层

      传输层              数据链路层

      网络层              物理层

      数据链路层

      物理层

  2. TCP\IP 协议存在 传输层   

    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 + "\n", "utf-8")) # 向服务端发送数据
    received = str(sock.recv(1024), "utf-8")# 从服务端接收数据

print("Sent:     {}".format(data))
print("Received: {}".format(received))
tcp_client_socketserver
相关文章
相关标签/搜索