TCP/IP協議 簡介
TCP/IP協議
一、層次劃分:
層次:鏈路層==>網絡層==>傳輸層==>應用層
理論層次:物理層==>數據鏈路層==>網絡層==>傳輸層==>會話層==>表示層==>應用層
應用層:解決要傳遞什麽數據
傳輸層:解決如何傳輸數據,udp/tcp
網絡層:解決地址問題,IP
鏈路層:具體傳輸工具
二、UDP(用戶數據包協議),註重速度,不夠穩定
#創建客戶端從服務器上下載文件
#coding=utf-8
from socket import *
import struct
import sys
if len(sys.argv) != 2:
print(‘-‘*30)
print("tips:")
print("python xxxx.py 192.168.1.1")
print(‘-‘*30)
exit()
else:
ip = sys.argv[1]
# 創建udp套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#構造下載請求數據
cmd_buf = struct.pack("!H8sb5sb",1,"test.jpg",0,"octet",0)
#發送下載文件請求數據到指定服務器
sendAddr = (ip, 69)
udpSocket.sendto(cmd_buf, sendAddr)
p_num = 0
recvFile = ‘‘
while True:
recvData,recvAddr = udpSocket.recvfrom(1024)
recvDataLen = len(recvData)
cmdTuple = struct.unpack("!HH", recvData[:4])
#得到操作號與數據包編號
cmd = cmdTuple[0]
currentPackNum = cmdTuple[1]
if cmd == 3: #是否為數據包
# 如果是第一次接收到數據,那麽就創建文件
if currentPackNum == 1:
recvFile = open("test.jpg", "a")
# 包編號是否和上次相等
if p_num+1 == currentPackNum:
recvFile.write(recvData[4:]);
p_num +=1
print ‘(%d)次接收到的數據‘%(p_num)
ackBuf = struct.pack("!HH",4,p_num)
udpSocket.sendto(ackBuf, recvAddr)
# 如果收到的數據小於516則認為出錯
if recvDataLen<516:
recvFile.close()
print ‘已經成功下載!!!‘
break
elif cmd == 5: #是否為錯誤應答
print "error num:%d"%currentPackNum
break
udpSocket.close()
UDP廣播(只有udp能用)
import socket
dest = (‘<broadcast>‘,端口號)
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#使用廣播時固定調用這句話
s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
s.sendto(‘hi‘,dest)
三、TCP(傳輸控制協議)
數據傳輸穩定,略慢於udp,web 服務器都是使用tcp
1、tcp服務器
from socket import *
serverSocket = socket(AF_INET,SOCK_STREAM)
serverSocket.bind((‘‘,7788))
serverSocket.listen(5)
#accept()返回值是一個元組
#clientSocket 表示這個新的客戶端
#clientInfo 表示新客戶端的IP和port
clientSocket,clientInfo = serverSocket.accept()
recvData = clientSocket.recv(1024)
print(‘%s:%s‘%(str(clientInfo),recvData))
clientSocket.close()
serverSocket.close()
2、tcp客戶端
manSocket = socket(AF_INET,SOCK_STREAM)
manSocker.connect((‘客戶端IP‘,4567))
sendData = imput(‘請輸入要傳輸的信息:‘)
#tcp已經鏈接好了服務器,所以發數據不用再寫IP和port
#udp因為沒有事先鏈接,所以每次發送都要寫IP和port
manSocker.send(sendData.encode(‘gb2312‘))
recvData = manSocker.recv(1024)
print(‘recvData:%s‘%recvData.decode(‘gb2312‘))
manSocker.close()
3、單進程服務器完成偽並發
#select,最多1024個元素,用輪詢方式檢測
#poll,解決了套接字上限的問題,輪詢方式檢測
#epoll,沒有上限,事件通知機制
from socket import *
import select
server = socket(AF_INET,SOCK_STREAM)
server.bind((‘‘,7788))
server.listen(1000)
list = [server]
while True:
#linux 中,select通過底層直接分別篩選三個列表,篩選條件分別為可接收數據,可發送數據,有異常信息
#沒有更新信息時默認堵塞,有新客戶訪問或已有客戶發信息時解堵塞
recvableList,list2,list3 = select.select(list,[],[])
for i in recvableList:
#有新的客戶端訪問時,服務端創建新的socket,並放入列表,等待下次循環篩選
if i == server:
newSocket,socketAddr = server.accept()
list.append(newSocket)
#客戶發送信息時,讀取發送的數據
else:
recvData = i.recv(1024)
if recvData:
i.send(recvData)
else:
#此時客戶端close(),下面移除select監聽的i這個socket
list.remove(i)
i.close()
4、其他備註:
a. ip地址和網絡掩碼按位與操作後,得到網絡號,網絡號相同則能夠相互通信
b. MAC地址,即網卡實際地址,由6個字節的十六進制數(12位)組成,前三字節表示生產廠家,後三位表示生產編號
c. icmp:ping一個電腦
d. arp:根據IP獲取一個電腦上的網卡號,就是Mac地址
e. rarp:根據Mac地址找IP
TCP/IP協議 簡介