第十八章 網(wǎng)絡編程socket的使用

Socket

TCP協(xié)議:

有請求 有響應 稱為TCP協(xié)議

是面向連接的協(xié)議,也就是說,在收發(fā)數(shù)據(jù)前,必須和對方建立可靠的連接。一個TCP連接必須要經(jīng)過三次“對話”才能建yc立起來,

如:網(wǎng)站請求

TCP三次握手的過程如下:

  1. 客戶端發(fā)送SYN(SEQ=x)報文給服務器端,進入SYN_SEND狀態(tài)。
  2. 服務器端收到SYN報文,回應一個SYN (SEQ=y)ACK(ACK=x+1)報文,進入SYN_RECV狀態(tài)。
  3. 客戶端收到服務器端的SYN報文,回應一個ACK(ACK=y+1)報文,進入Established狀態(tài)。

三次握手完成,TCP客戶端和服務器端成功地建立連接,可以開始傳輸數(shù)據(jù)了。

UDP協(xié)議:

? UDP是一個非連接的協(xié)議,傳輸數(shù)據(jù)之前源端和終端不建立連接

用到的應用:如飛秋 qq

一 什么是 Socket?

Socket又稱"套接字",應用程序通常通過"套接字"向網(wǎng)絡發(fā)出請求或者應答網(wǎng)絡請求,使主機間或者一臺計算機上的進程間可以通訊。


socket()函數(shù)

Python 中,我們用 socket()函數(shù)來創(chuàng)建套接字,語法格式如下:

socket.socket([family[, type[, proto]]])

參數(shù)

  • family: 套接字家族可以使AF_UNIX或者AF_INET
    • AF_INET 使用IPv4協(xié)議
    • AF_INET6 使用IPv6協(xié)議
  • type: 套接字類型可以根據(jù)是面向連接的還是非連接分為SOCK_STREAMSOCK_DGRAM
    • SOCK_STREAM (TCP連接)
    • SOCK_DGRAM(UDP連接)
  • protocol: 一般不填默認為0.
socket() 分別傳遞不同的域AF_INET和AF_UNIX
bind()的地址結構分別為sockaddr_in(制定IP端口)和sockaddr_un(指定路徑名)
2 AF_INET需經(jīng)過多個協(xié)議層的編解碼,消耗系統(tǒng)cpu,并且數(shù)據(jù)傳輸需要經(jīng)過網(wǎng)卡,受到網(wǎng)卡帶寬的限制。AF_UNIX數(shù)據(jù)到達內(nèi)核緩沖區(qū)后,由內(nèi)核根據(jù)指定路徑名找到接收方socket對應的內(nèi)核緩沖區(qū),直接將數(shù)據(jù)拷貝過去,不經(jīng)過協(xié)議層編解碼,節(jié)省系統(tǒng)cpu,并且不經(jīng)過網(wǎng)卡,因此不受網(wǎng)卡帶寬的限制。
3 AF_UNIX的傳輸速率遠遠大于AF_INET
AF_INET不僅可以用作本機的跨進程通信,同樣的可以用于不同機器之間的通信,其就是為了在不同機器之間進行網(wǎng)絡互聯(lián)傳遞數(shù)據(jù)而生。而AF_UNIX則只能用于本機內(nèi)進程之間的通信。

使用場景

AF_UNIX由于其對系統(tǒng)cpu的較少消耗,不受限于網(wǎng)卡帶寬,及高效的傳遞速率,本機通信則首選AF_UNIX域。

不用多說,AF_INET則用于跨機器之間的通信。

二 創(chuàng)建UDP協(xié)議的客戶端和服務端

端口數(shù)值的取值范圍是0~65535
端口數(shù)小于1024的都是為眾所周知的網(wǎng)絡服務所保留的
地址127.0.0.1是本機地址;它始終指向當前的計算機。程序可以使用這個地址來連接運行在同一計算機上的其它程序。
常用函數(shù):
  1. gethostname()返回運行程序所在的計算機的主機名:
>>> import socket
>>> socket.gethostname()
'lenovo'
  1. gethostbyname(name) 嘗試將給定的主機名解釋為一個IP地址
>>> socket.gethostbyname('lenovo
'192.168.1.4'
>>> socket.gethostbyname('www.jb51.net')
'222.76.216.16'

(1) 客戶端

實例:

import socket

#建立一個UDP的客戶端

udp = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

while True:

    data = input("請輸入你要說的話")

    udp.sendto(data.encode("utf-8"),("127.0.0.1",8858))  #發(fā)送UDP數(shù)據(jù),將數(shù)據(jù)發(fā)送到套接字,address是形式為(ipaddr,port)的元組,指定遠程地址。返回值是發(fā)送的字節(jié)數(shù)。

(2) 服務端

實例:

import socket

#建立一個UDP的服務端
udpServer = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

#127.0.0.1 - 127.255.255.254 都屬于訪問本地  但是都是用 127.0.0.1
udpServer.bind(("127.0.0.1",8858))

while True:

    data,addr = udpServer.recvfrom(1024)   #接收UDP數(shù)據(jù),與recv()類似,但返回值是(data,address)。其中data是包含接收數(shù)據(jù)的字符串,address是發(fā)送數(shù)據(jù)的套接字地址。

   print("消息為:",data.decode("utf-8"),"地址為",addr)  

三 創(chuàng)建TCP協(xié)議的客戶端和服務端

(1) 創(chuàng)建TCP客戶端

實例

import socket

tcpClient = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

tcpClient.connect(("127.0.0.1",8000)) #主動初始化TCP服務器連接,。一般address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。

while True:
    data = input("輸入倆天內(nèi)容")
    tcpClient.send(data.encode("utf-8"))  #發(fā)送TCP數(shù)據(jù),將string中的數(shù)據(jù)發(fā)送到連接的套接字。返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于string的字節(jié)大小。
    mydata = tcpClient.recv(1024)  #接收TCP數(shù)據(jù),數(shù)據(jù)以字符串形式返回,bufsize指定要接收的最大數(shù)據(jù)量。flag提供有關消息的其他信息,通??梢院雎?。
    print(mydata.decode("utf-8"))

(2) 創(chuàng)建TCP服務端

實例:

import socket
tcpServer = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcpServer.bind(("127.0.0.1",8000))   #綁定地址(host,port)到套接字, 在AF_INET下,以元組(host,port)的形式表示地址。
tcpServer.listen(5) #設置監(jiān)聽數(shù) ,最大連接數(shù),超過后排隊
clientSock,addr = tcpServer.accept()  #被動接受TCP客戶端連接,(阻塞式)等待連接的到來
while True:
    data = clientSock.recv(1024)    #接收TCP數(shù)據(jù)最大值為1字節(jié)
    print("時間為", time.strftime("%Y-%m-%d %H:%M:%S"))
    print("收到了",data.decode("utf-8"))
    mydata = input("聊天內(nèi)容")
    clientSock.send(mydata.encode("utf-8"))

四 使用socket請求網(wǎng)址

import socket
# 創(chuàng)建一個socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連接:
s.connect(('www.xialigang.com', 80))  
s.send(b'GET / HTTP/1.1\r\nHost: www.xialigang.com\r\nConnection: close\r\n\r\n')
buffer = []
while True:
    # 每次最多接收1k字節(jié):
    d = s.recv(1024)
    if d:
        buffer.append(d)
    else:
        break
data = b''.join(buffer)  #將列表的數(shù)據(jù)進行連接
#把HTTP頭和網(wǎng)頁分離一下,把HTTP頭打印出來,網(wǎng)頁內(nèi)容保存到文件:
header, html = data.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
print(html)

五 Socket 對象(內(nèi)建)方法

函數(shù) 描述
服務器端套接字
s.bind() 綁定地址(host,port)到套接字, 在AF_INET下,以元組(host,port)的形式表示地址。
s.listen() 開始TCP監(jiān)聽。backlog指定在拒絕連接之前,操作系統(tǒng)可以掛起的最大連接數(shù)量。該值至少為1,大部分應用程序設為5就可以了。
s.accept() 被動接受TCP客戶端連接,(阻塞式)等待連接的到來
客戶端套接字
s.connect() 主動初始化TCP服務器連接,。一般address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。
s.connect_ex() connect()函數(shù)的擴展版本,出錯時返回出錯碼,而不是拋出異常
公共用途的套接字函數(shù)
s.recv() 接收TCP數(shù)據(jù),數(shù)據(jù)以字符串形式返回,bufsize指定要接收的最大數(shù)據(jù)量。flag提供有關消息的其他信息,通常可以忽略。
s.send() 發(fā)送TCP數(shù)據(jù),將string中的數(shù)據(jù)發(fā)送到連接的套接字。返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于string的字節(jié)大小。
s.sendall() 完整發(fā)送TCP數(shù)據(jù),完整發(fā)送TCP數(shù)據(jù)。將string中的數(shù)據(jù)發(fā)送到連接的套接字,但在返回之前會嘗試發(fā)送所有數(shù)據(jù)。成功返回None,失敗則拋出異常。
s.recvfrom() 接收UDP數(shù)據(jù),與recv()類似,但返回值是(data,address)。其中data是包含接收數(shù)據(jù)的字符串,address是發(fā)送數(shù)據(jù)的套接字地址。
s.sendto() 發(fā)送UDP數(shù)據(jù),將數(shù)據(jù)發(fā)送到套接字,address是形式為(ipaddr,port)的元組,指定遠程地址。返回值是發(fā)送的字節(jié)數(shù)。
s.close() 關閉套接字
s.getpeername() 返回連接套接字的遠程地址。返回值通常是元組(ipaddr,port)。
s.getsockname() 返回套接字自己的地址。通常是一個元組(ipaddr,port)
s.setsockopt(level,optname,value) 設置給定套接字選項的值。
s.getsockopt(level,optname[.buflen]) 返回套接字選項的值。
s.settimeout(timeout) 設置套接字操作的超時期,timeout是一個浮點數(shù),單位是秒。值為None表示沒有超時期。一般,超時期應該在剛創(chuàng)建套接字時設置,因為它們可能用于連接的操作(如connect())
s.gettimeout() 返回當前超時期的值,單位是秒,如果沒有設置超時期,則返回None。
s.fileno() 返回套接字的文件描述符。
s.setblocking(flag) 如果flag為0,則將套接字設為非阻塞模式,否則將套接字設為阻塞模式(默認值)。非阻塞模式下,如果調(diào)用recv()沒有發(fā)現(xiàn)任何數(shù)據(jù),或send()調(diào)用無法立即發(fā)送數(shù)據(jù),那么將引起socket.error異常。
s.makefile() 創(chuàng)建一個與該套接字相關連的文件
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 網(wǎng)絡編程 一.楔子 你現(xiàn)在已經(jīng)學會了寫python代碼,假如你寫了兩個python文件a.py和b.py,分別去運...
    go以恒閱讀 2,238評論 0 6
  • 什么是Socket Socket是進程通訊的一種方式,即調(diào)用這個網(wǎng)絡庫的一些API函數(shù)實現(xiàn)分布在不同主機的相關進程...
    onlyHalfSoul閱讀 702評論 0 1
  • 一、網(wǎng)絡各個協(xié)議:TCP/IP、SOCKET、HTTP等 網(wǎng)絡七層由下往上分別為物理層、數(shù)據(jù)鏈路層、網(wǎng)絡層、傳輸層...
    杯水救車薪閱讀 2,358評論 0 17
  • 3 socket模塊-TCP gitbook鏈接:用python帶你進入AI中的深度學習技術領域https://w...
    scrappyzhang閱讀 1,280評論 0 2
  • 一、加密方法一覽 Base64 (不知道算啥) 哈希函數(shù) (散列)MD5SHA1SHA256/512 對稱加密算...
    Lucus_Linx閱讀 281評論 0 0

友情鏈接更多精彩內(nèi)容