網絡編程知識點剖析

網絡編程知識點剖析前端

. 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
相關文章
相關標籤/搜索