天天看點

網絡通信,IP位址, 端口,socket

目錄

1. 什麼是網絡

2. 使用網絡的目的

ip位址

1. 什麼是位址

2. ip位址的作用

檢視或配置網卡資訊:ipconfig

測試遠端主機連通性:ping

3. ip位址的分類(了解)

端口

1. 什麼是端口

2. 端口号

3. 端口是怎樣配置設定的

4. 小總結

socket簡介

1. 不同電腦上的程序之間如何通信

2. 什麼是socket

3. 建立socket

說明

  • 網絡就是一種輔助雙方或者多方能夠連接配接在一起的工具
  • 如果沒有網絡可想

    單機

    的世界是多麼的孤單

單機遊戲(不能和遠在他鄉的朋友一起玩)

網絡通信,IP位址, 端口,socket

就是為了聯通多方然後進行通信用的,即把資料從一方傳遞給另外一方

前面的學習編寫的程式都是單機的,即不能和其他電腦上的程式進行通信

為了讓在不同的電腦上運作的軟體,之間能夠互相傳遞資料,就需要借助網絡的功能

小總結

  • 使用網絡能夠把多方連結在一起,然後可以進行資料傳遞
  • 所謂的網絡程式設計就是,讓在不同的電腦上的軟體能夠進行資料傳遞,即程序之間的通信
網絡通信,IP位址, 端口,socket

網絡通信,IP位址, 端口,socket

位址就是用來标記地點的

網絡通信,IP位址, 端口,socket

ip位址:用來在網絡中标記一台電腦,比如192.168.1.1;在本地區域網路上是唯一的。

如果,我們隻是敲:ipconfig,它會顯示所有網卡的資訊:

通常用ping來檢測網絡是否正常

每一個IP位址包括兩部分:網絡位址和主機位址

網絡通信,IP位址, 端口,socket
網絡通信,IP位址, 端口,socket

3.1 A類IP位址

一個A類IP位址由1位元組的網絡位址和3位元組主機位址組成,網絡位址的最高位必須是“0”,

位址範圍1.0.0.1-126.255.255.254

二進制表示為:00000001 00000000 00000000 00000001 - 01111110 11111111 11111111 11111110

可用的A類網絡有126個,每個網絡能容納1677214個主機

3.2 B類IP位址

一個B類IP位址由2個位元組的網絡位址和2個位元組的主機位址組成,網絡位址的最高位必須是“10”,

位址範圍128.1.0.1-191.255.255.254

二進制表示為:10000000 00000001 00000000 00000001 - 10111111 11111111 11111111 11111110

可用的B類網絡有16384個,每個網絡能容納65534主機

3.3 C類IP位址

一個C類IP位址由3位元組的網絡位址和1位元組的主機位址組成,網絡位址的最高位必須是“110”

範圍192.0.1.1-223.255.255.254

二進制表示為: 11000000 00000000 00000001 00000001 - 11011111 11111111 11111110 11111110

C類網絡可達2097152個,每個網絡能容納254個主機

3.4 D類位址用于多點廣播

單點傳播,多點傳播(一對幾個),廣播(一對所有)

D類IP位址第一個位元組以“1110”開始,它是一個專門保留的位址。

它并不指向特定的網絡,目前這一類位址被用在多點廣播(Multicast)中

多點廣播位址用來一次尋址一組計算機 s 位址範圍224.0.0.1-239.255.255.254

3.5 E類IP位址

以“1111”開始,為将來使用保留

E類位址保留,僅作實驗和開發用

3.6 私有ip

在這麼多網絡IP中,國際規定有一部分IP位址是用于我們的區域網路使用,也就

是屬于私網IP,不在公網中使用的,它們的範圍是:

10.0.0.0~10.255.255.255

172.16.0.0~172.31.255.255

192.168.0.0~192.168.255.255
           

3.7 注意

IP位址127.0.0.1~127.255.255.255用于回路測試,

如:127.0.0.1可以代表本機IP位址,用

http://127.0.0.1

就可以測試本機中配置的Web伺服器。

網絡通信,IP位址, 端口,socket

端口就好一個房子的門,是出入這間房子的必經之路。

如果一個程式需要收發網絡資料,那麼就需要有這樣的端口

在linux系統中,端口可以有65536(2的16次方)個之多!

既然有這麼多,作業系統為了統一管理,是以進行了編号,這就是

端口号

網絡通信必備ip和端口号

程序是運作起來的程式。

端口是通過端口号來标記的,端口号隻有整數,範圍是從0到65535

注意:端口數不一樣的*nix系統不一樣,還可以手動修改

端口号不是随意使用的,而是按照一定的規定進行配置設定。

端口的分類标準有好幾種,我們這裡不做詳細講解,隻介紹一下知名端口和動态端口

3.1 知名端口(Well Known Ports)

知名端口是衆所周知的端口号,範圍從0到1023

80端口配置設定給HTTP服務
21端口配置設定給FTP服務
           

可以了解為,一些常用的功能使用的号碼是估計的,好比 電話号碼110、10086、10010一樣

網絡通信,IP位址, 端口,socket

一般情況下,如果一個程式需要使用知名端口的需要有root權限

3.2 動态端口(Dynamic Ports)

動态端口的範圍是從1024到65535

之是以稱為動态端口,是因為它一般不固定配置設定某種服務,而是動态配置設定。

動态配置設定是指當一個系統程式或應用程式程式需要網絡通信時,它向主機申請一個端口,主機從可用的端口号中配置設定一個供它使用。

當這個程式關閉時,同時也就釋放了所占用的端口号

3.3 怎樣檢視端口 ?

  • 用“netstat -an”檢視端口狀态
  • lsof -i [tcp/udp]:2425

端口有什麼用呢 ? 我們知道,一台擁有IP位址的主機可以提供許多服務,比如HTTP(網際網路服務)、FTP(檔案傳輸)、SMTP(電子郵件)等,這些服務完全可以通過1個IP位址來實作。那麼,主機是怎樣區分不同的網絡服務呢?顯然不能隻靠IP位址,因為IP位址與網絡服務的關系是一對多的關系。實際上是通過“IP位址+端口号”來區分不同的服務的。 需要注意的是,端口并不是一一對應的。比如你的電腦作為客戶機通路一台WWW伺服器時,WWW伺服器使用“80”端口與你的電腦通信,但你的電腦則可能使用“3457”這樣的端口。

首要解決的問題是如何唯一辨別一個程序,否則通信無從談起!

在1台電腦上可以通過程序号(PID)來唯一辨別一個程序,但是在網絡中這是行不通的。

其實TCP/IP協定族已經幫我們解決了這個問題,網絡層的“ip位址”可以唯一辨別網絡中的主機,而傳輸層的“協定+端口”可以唯一辨別主機中的應用程序(程序)。

這樣利用ip位址,協定,端口就可以辨別網絡的程序了,網絡中的程序通信就可以利用這個标志與其它程序進行互動

注意:

  • 所謂

    程序

    指的是:運作的程式以及運作時用到的資源這個整體稱之為程序(在講解多任務程式設計時進行詳細講解)
  • 程序間通信

    指的是:運作的程式之間的資料共享
  • 後面課程中會詳細說到,像網絡層等知識,不要着急

socket(簡稱 

套接字

) 是程序間通信的一種方式,它與其他程序間通信的一個主要不同是:

它能實作不同主機間的程序間通信,我們網絡上各種各樣的服務大多都是基于 Socket 來完成通信的

例如我們每天浏覽網頁、QQ 聊天、收發 email 等等

網絡通信,IP位址, 端口,socket
網絡通信,IP位址, 端口,socket

在 Python 中 使用socket 子產品的函數 socket 就可以完成:

import socket
socket.socket(AddressFamily, Type)
           

說明:

函數 socket.socket 建立一個 socket,該函數帶有兩個參數:

  • Address Family:可以選擇 AF_INET(用于 Internet 程序間通信) 或者 AF_UNIX(用于同一台機器程序間通信),實際工作中常用AF_INET, IPV4/IPV6
  • Type:套接字類型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 協定)或者 SOCK_DGRAM(資料報套接字,主要用于 UDP 協定)

建立一個tcp socket(tcp套接字)

import socket

# 建立tcp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# ...這裡是使用套接字的功能(省略)...

# 不用的時候,關閉套接字
s.close()
           

建立一個udp socket(udp套接字)

import socket

# 建立udp的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# ...這裡是使用套接字的功能(省略)...

# 不用的時候,關閉套接字
s.close()
           
  • 套接字使用流程 與 檔案的使用流程很類似
    1. 建立套接字
    2. 使用套接字收/發資料
    3. 關閉套接字

測試代碼 

'''
伺服器

和用戶端程式設計相比,伺服器程式設計就要複雜一些。
'''
'''
伺服器程序首先要綁定一個端口并監聽來自其他用戶端的連接配接。
如果某個用戶端連接配接過來了,伺服器就與該用戶端建立Socket連接配接,随後的通信就靠這個Socket連接配接了。
'''
'''
伺服器會打開固定端口(比如80)監聽,每來一個用戶端連接配接,就建立該Socket連接配接。
由于伺服器會有大量來自用戶端的連接配接,是以,伺服器要能夠區分一個Socket連接配接是和哪個用戶端綁定的。
一個Socket依賴4項:伺服器位址、伺服器端口、用戶端位址、用戶端端口來唯一确定一個Socket。
'''
'''
伺服器還需要同時響應多個用戶端的請求
是以,每個連接配接都需要一個新的程序或者新的線程來處理,否則,伺服器一次就隻能服務一個用戶端了。
'''
'''
伺服器可能有多塊網卡,可以綁定到某一塊網卡的IP位址上,也可以用0.0.0.0綁定到所有的網絡位址,還可以用127.0.0.1綁定到本機位址。
127.0.0.1是一個特殊的IP位址,表示本機位址,如果綁定到這個位址,用戶端必須同時在本機運作才能連接配接,也就是說,外部的計算機無法連接配接進來。
'''
'''
編寫一個簡單的伺服器程式

它接收用戶端連接配接,把用戶端發過來的字元串加上Hello再發回去。
'''
import socket
import threading
import time


# 每個連接配接都必須建立新線程(或程序)來處理
# 否則,單線程在處理連接配接的過程中,無法接受其他用戶端的連接配接:
def tcplink(sock,addr):
    print('Accept new connection from %s:%s...' % addr)
    sock.send(b'Welcome!')
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if not data or data.decode('utf-8') == 'exit':
            break
        sock.send(('Hello Python Server,%s!' % data.decode('utf-8')).encode('utf-8'))
    sock.close()
    print('Connection from %s:%s closed.' % addr)


# 建立一個基于IPv4和TCP協定的Socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 綁定監聽的位址和端口
s.bind(('127.0.0.1', 2222))

# 調用listen()方法開始監聽端口,傳入的參數指定等待連接配接的最大數量
s.listen(5)
print('Waiting for connection...')

# 伺服器程式通過一個永久循環來接受來自用戶端的連接配接
# accept()會等待并傳回一個用戶端的連接配接:
while True:
    # 接受一個新連接配接:
    sock, addr = s.accept()
    print('addr:',addr)
    # 建立新線程來處理TCP連接配接:
    t = threading.Thread(target = tcplink, args=(sock,addr))
    t.start()

           
'''
測試伺服器程式,我們還需要編寫一個用戶端程式:
'''
import socket

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 建立連接配接:
s.connect(('127.0.0.1',2222))
# 接收歡迎消息:
print(s.recv(1024).decode('utf-8'))
for data in [b'Michael',b'Tracy',b'Jue']:
    # 發送資料:
    s.send(data)
    print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
           

繼續閱讀