網絡由下往上分爲物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。php
HTTP是高層協議,而TCP/IP是個協議集,包過許多的子協議。包括:傳輸層的 FTP,UDP,TCP協議等,網絡層的ip協議等,高層協議如HTTP,telnet協議等,HTTP是TCP/IP的一個子協議。html
socket是對TCP/IP協議的封裝和應用(程序員層面上)。也能夠說,TPC/IP協議是傳輸層協議,主要解決數據如何在網絡中傳輸,而HTTP是應用層協議,主要解決如何包裝數據。python
咱們在傳輸數據時,能夠只使用(傳輸層)TCP/IP協議,可是那樣的話,若是沒有應用層,便沒法識別數據內容,若是想要使傳輸的數據有意義,則必須使用到應用層協議,應用層協議有不少,好比HTTP、FTP、TELNET等,也能夠本身定義應用層協議。WEB使用HTTP協議做應用層協議,以封裝HTTP文本信息,而後使用TCP/IP作傳輸層協議將它發到網絡上。程序員
而咱們平時說的最多的socket是什麼呢,實際上socket是對TCP/IP協議的封裝,Socket自己並非協議,而是一個調用接口(API),經過Socket,咱們才能使用TCP/IP協議。實際上,Socket跟TCP/IP協議沒有必然的聯繫。Socket編程接口在設計的時候,就但願也能適應其餘的網絡協議。因此說,Socket的出現只是使得程序員更方便地使用TCP/IP協議棧而已,是對TCP/IP協議的抽象,從而造成了咱們知道的一些最基本的函數接口,好比create、listen、connect、accept、send、read和write等等。數據庫
TCP/IP只是一個協議棧,就像操做系統的運行機制同樣,必需要具體實現,同時還要提供對外的操做接口。這個就像操做系統會提供標準的編程接口,好比win32編程接口同樣,TCP/IP也要提供可供程序員作網絡開發所用的接口,這就是Socket編程接口。編程
有個比較形象的描述:HTTP是轎車,提供了封裝或者顯示數據的具體形式;Socket是發動機,提供了網絡通訊的能力。服務器
實際上,傳輸層的TCP是基於網絡層的IP協議的,而應用層的HTTP協議又是基於傳輸層的TCP協議的,而Socket自己不算是協議,就像上面所說,它只是提供了一個針對TCP或者UDP編程的接口。網絡
利用Socket創建網絡鏈接的步驟:dom
創建Socket鏈接至少須要一對套接字,其中一個運行於客戶端,稱爲ClientSocket ,另外一個運行於服務器端,稱爲ServerSocket 。socket
套接字之間的鏈接過程分爲三個步驟:服務器監聽,客戶端請求,鏈接確認。
1。服務器監聽:服務器端套接字並不定位具體的客戶端套接字,而是處於等待鏈接的狀態,實時監控網絡狀態,等待客戶端的鏈接請求。
2。客戶端請求:指客戶端的套接字提出鏈接請求,要鏈接的目標是服務器端的套接字。爲此,客戶端的套接字必須首先描述它要鏈接的服務器的套接字,指出服務器端套接字的地址和端口號,而後就向服務器端套接字提出鏈接請求。
3。鏈接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的鏈接請求時,就響應客戶端套接字的請求,創建一個新的線程,把服務器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式創建鏈接。而服務器端套接字繼續處於監聽狀態,繼續接收其餘客戶端套接字的鏈接請求。
HTTP連接的特色
HTTP協議即超文本傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網經常使用的協議之一,HTTP協議是創建在TCP協議之上的一種應用。
HTTP鏈接最顯著的特色是客戶端發送的每次請求都須要服務器回送響應,在請求結束後,會主動釋放鏈接。從創建鏈接到關閉鏈接的過程稱爲「一次鏈接」。
The Internet Protocol(協議)
IP就是一個32位無符號整數。IP地址經過DNS (Domain Name System) 數據庫映射到域名
1
2
3
4
5
6
7
|
#!/usr/bin/env python
# Foundations of Python Network Programming - Chapter 1 - getname.py
import
socket
hostname
=
'google.com'
addr
=
socket.gethostbyname(hostname)
print
'The address of'
, hostname,
'is'
, addr
# The address of google.com is 173.194.72.113
|
Python網絡編程:
Python提供了訪問底層操做系統Socket接口的所有方法,還提供了一組加密和認證通訊的服務,SSL/TLS。
Sockets實際上是一個文件描述符,不一樣於不一樣於本地文件,它鏈接了網絡上的一個文件。
一、建立一個UDP 本地鏈接:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#!/usr/bin/env python
import
socket, sys
s
=
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
MAX
=
65535
PORT
=
1060
s.bind((
'127.0.0.1'
, PORT))
print
'Listening at'
, s.getsockname()
while
True
:
data, address
=
s.recvfrom(
MAX
)
print
'The client at'
, address,
'says'
,
repr
(data)
s.sendto(
'Your data was %d bytes'
%
len
(data), address)
elif
sys.argv[
1
:]
=
=
[
'client'
]:
print
'Address before sending:'
, s.getsockname()
s.sendto(
'This is my message'
, (
'127.0.0.1'
, PORT))
print
'Address after sending'
, s.getsockname()
data, address
=
s.recvfrom(
MAX
)
# overly promiscuous - see text!
print
'The server'
, address,
'says'
,
repr
(data)
else
:
|
運行這段代碼:
1
2
3
4
5
6
7
|
python filename.py server
#Listening at (
'127.0.0.1'
,
1060
)
#Address before sending: (
'0.0.0.0'
,
0
)
#Address after sending (
'0.0.0.0'
,
62892
)
#The server (
'127.0.0.1'
,
1060
) says
'Your data was 18 bytes'
python filename.py client
#The client at (
'127.0.0.1'
,
62892
) says
'This is my message'
|
二、建立遠程鏈接並驗證收到的信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
import
random, socket, sys
s
=
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
MAX
=
65535
PORT
=
1060
interface
=
sys.argv[
2
]
if
len
(sys.argv) >
2
else
''
s.bind((interface, PORT))
print
'Listening at'
, s.getsockname()
while
True
:
data, address
=
s.recvfrom(
MAX
)
if
random.randint(
0
,
1
):
print
'The client at'
, address,
'says:'
,
repr
(data)
s.sendto(
'Your data was %d bytes'
%
len
(data), address)
else
:
print
'Pretending to drop packet from'
, address
elif
len
(sys.argv)
=
=
3
and
sys.argv[
1
]
=
=
'client'
:
hostname
=
sys.argv[
2
]
s.connect((hostname, PORT))
print
'Client socket name is'
, s.getsockname()
delay
=
0.1
while
True
:
s.send(
'This is another message'
)
print
'Waiting up to'
, delay,
'seconds for a reply'
s.settimeout(delay)
try
:
data
=
s.recv(
MAX
)
except
socket.timeout:
delay
*
=
2
# wait even longer for the next request
if
delay >
2.0
:
raise
RuntimeError(
'I think the server is down'
)
else
:
break
# we are done, and can stop looping
print
'The server says'
,
repr
(data)
else
:
print
>>sys.stderr,
' or: udp_remote.py client <host>'
sys.exit(
2
)
|
這裏的s.connect((hostname, PORT))方法,可讓咱們不用每次都調用s.sendto('This is my message', ('127.0.0.1', PORT))。直接調用
s.send('This is another message')。