應用層: 它只負責產生相應格式的數據 ssh ftp nfs cifs dns http smtp pop3
傳輸層: 定義數據傳輸的兩種模式:
TCP(傳輸控制協議:面向連接,可靠的,效率相對不高)
UDP(用戶數據報協議:非面向連接,不可靠的,但效率高)
網絡層: 連接不同的網絡如以太網、令牌環網
IP (路由,分片) 、ICMP、 IGMP
ARP ( 地址解析協議,作用是將IP解析成MAC )
數據鏈路層: 以太網傳輸
物理層: 主要任務是規定各種傳輸介質和接口與傳輸信號相關的一些特性
tcp協議:三次握手四次揮手
socket(套接字):
tcp:

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() #關閉服務器套接字(可選)

import socket sk = socket.socket() # 創建客戶套接字 sk.connect(('127.0.0.1',8898)) # 嘗試連接服務器 sk.send(b'hello!') ret = sk.recv(1024) # 對話(發送/接收) print(ret) sk.close() # 關閉客戶套接字
udp

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() # 關閉服務器套接字

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)
黏包問題:
黏包現象只發生在tcp協議中:
1.從表面上看,黏包問題主要是因為發送方和接收方的緩存機制、tcp協議面向流通信的特點。
2.實際上,主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節的數據所造成的
解決黏包問題:
struct模塊
該模塊可以把一個類型,如數字,轉成固定長度的bytes

import socket import struct sk=socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() conn,addr = sk.accept() while True: info = input("<<<") if info =="q": break conn.send(info.encode('utf-8')) msg = conn.recv(4) ret=struct.unpack('i',msg)[0] ret=conn.recv(ret) print(ret.decode('gbk')) conn.close() sk.close()

import socket import subprocess import struct sk = socket.socket() sk.connect(('127.0.0.1',9000)) while True: cmd=sk.recv(1024) if cmd == 'q': break res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stderr=subprocess.PIPE, stdin=subprocess.PIPE, stdout=subprocess.PIPE) stderr = res.stderr.read() stdout = res.stdout.read() ret=len(stderr)+len(stdout) ret=struct.pack('i',ret) sk.send(ret) sk.send(stderr) sk.send(stdout) sk.close()
上傳下載文件:

import socket import os import json import struct buffer=1024 sk=socket.socket() sk.bind(('127.0.0.1',8880))#把地址綁定到套接字 sk.listen()#監聽鏈接 conn,addr = sk.accept() #接受客戶端鏈接 head_len = conn.recv(4) head_len = struct.unpack('i',head_len)[0] json_head = conn.recv(head_len).decode('utf-8') head = json.loads(json_head) file_size = head['file_size'] with open(head['file_name'],'wb')as f: while file_size: if file_size >= buffer: c=conn.recv(buffer) f.write(c) file_size -= buffer else: c=conn.recv(file_size) f.write(c) break conn.close() sk.close()

import socket import os import json import struct sk = socket.socket() # 創建客戶套接字 sk.connect(('127.0.0.1',8880)) buffer = 1024 head = {'file_size': None, 'file_path' : r'C:\Users\tom\Pictures\2016-10', 'file_name': 'IMG_0116.JPG'} filepath = os.path.join(head['file_path'], head['file_name']) file_size = os.path.getsize(filepath) head['file_size'] = file_size head_json = json.dumps(head)#字典轉字符串 head_bytes = head_json.encode('utf-8')#轉bytes head_len = len(head_bytes) pack_len = struct.pack('i',head_len) sk.send(pack_len) #先發報頭的長度,4個bytes sk.send(head_bytes) #再發報頭的字節格式 with open(filepath,'rb') as f: while file_size : if file_size > buffer: c=f.read(buffer) sk.send(c) file_size-=buffer else: c = f.read(file_size) sk.send(c) break sk.close()