python網(wǎng)絡(luò)編程

1. 網(wǎng)絡(luò)編程基礎(chǔ)

  • 網(wǎng)絡(luò)編程:讓不同電腦上的軟件進(jìn)行數(shù)據(jù)傳遞,即進(jìn)程間通信饮睬。
  • IP地址:用來(lái)標(biāo)記網(wǎng)絡(luò)主機(jī)秸谢。
  • 每一個(gè)IP地址包括兩部分:網(wǎng)絡(luò)地址和主機(jī)地址。根據(jù)網(wǎng)絡(luò)地址和主機(jī)地址分為:A B C D E類奢驯。具體內(nèi)容參考:https://www.cnblogs.com/tunian/p/9632893.html
  • 端口:端口通過(guò)端口號(hào)標(biāo)記,可通過(guò)IP+端口號(hào)來(lái)區(qū)分不同服務(wù)次绘。常用端口對(duì)照表:https://blog.csdn.net/l_smalltiger/article/details/81951824

2. 套接字

套接字是一種“通信端點(diǎn)”瘪阁,網(wǎng)絡(luò)化的應(yīng)用程序在開始任何通訊之前需要?jiǎng)?chuàng)建套接字。套接字分類:

面向連接的套接字:在通訊之前建立一條連接邮偎,也稱為流套接字管跺。面向連接的通信方式提供了可靠的、順序的禾进、不會(huì)重復(fù)的數(shù)據(jù)傳輸伙菜,也不會(huì)被加上數(shù)據(jù)邊界。這也代表每個(gè)發(fā)送的消息可能會(huì)被拆為多份命迈,沒有順序地正確到達(dá)目的地,然后被重新拼接起來(lái)火的。實(shí)現(xiàn)這種連接的主要協(xié)議是傳輸控制協(xié)議(TCP)壶愤。創(chuàng)建TCP套接字需要指定套接字類型為SOCK_STREAM。

無(wú)連接即數(shù)據(jù)報(bào)型的無(wú)連接套接字馏鹤。即無(wú)需建立連接就可進(jìn)行通訊征椒,但此時(shí)數(shù)據(jù)到達(dá)的順序、完整性及不重復(fù)性無(wú)法保證湃累。數(shù)據(jù)報(bào)會(huì)保留數(shù)據(jù)邊界勃救,即數(shù)據(jù)是整個(gè)發(fā)送的。實(shí)現(xiàn)這種連接的主要協(xié)議是用戶數(shù)據(jù)報(bào)協(xié)議(UDP)治力。創(chuàng)建UDP套接字需要指定套接字類型為SOCK_DGRAM蒙秒。

2.1 套接字使用:

套接字使用流程和文件很相似:創(chuàng)建套接字、使用套接字收發(fā)數(shù)據(jù)宵统、關(guān)閉套接字晕讲。

python使用socket()模塊來(lái)創(chuàng)建套接字,完成基于套接字的網(wǎng)絡(luò)通信。

函數(shù) socket.socket() 創(chuàng)建一個(gè) socket瓢省,該函數(shù)帶有兩個(gè)參數(shù):

  • Address Family:可以選擇 AF_INET(用于 Internet 進(jìn)程間通信) 或者 AF_UNIX(用于同一臺(tái)機(jī)器進(jìn)程間通信),實(shí)際工作中常用AF_INET
  • Type:套接字類型弄息,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 協(xié)議)或者 SOCK_DGRAM(數(shù)據(jù)報(bào)套接字勤婚,主要用于 UDP 協(xié)議)

套接字中常用的函數(shù)如下:

image
image
2.2 udp套接字

udp通信模型

img

udp服務(wù)器

recvfrom方法:

  • data, addr = server_socket.recvfrom()
  • 方法返回兩個(gè)值摹量,第一個(gè)值為接收到的二進(jìn)制數(shù)據(jù),第二個(gè)數(shù)據(jù)是一個(gè)元組形式(IP, PORT)馒胆,標(biāo)記客戶端的地址缨称。第一個(gè)元素為客戶端的IP地址字符串,第二個(gè)元素為客戶端端口號(hào)国章。

sendto方法:

  • server_socket.sentto(data, addr)
  • sendto方法接受兩個(gè)參數(shù)具钥,第一個(gè)為發(fā)送的數(shù)據(jù)(二進(jìn)制形式,需要編碼)液兽,第二個(gè)為客戶端的地址(從recvfrom方法得到)
img
import socket

# 定義服務(wù)器IP及端口
HOST = ""  # 字符串留空或者localhost代表本地骂删,也可自定義Ip
PORT = 7890
ADDR = (HOST, PORT)

def main():
    # 定義服務(wù)器套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 綁定地址
    server_socket.bind(ADDR)

    # 通信循環(huán):收發(fā)消息
    while True:
        print("waiting for messages......")

        # 接受客戶端消息
        recv_data, addr = server_socket.recvfrom(1024)
        print("receive messages:%s from %s" % (recv_data.decode("gbk"), str(addr)))

        if recv_data.decode("gbk") == "exit":
            break

        # 發(fā)送消息到客戶端
        send_data = "我是UDP服務(wù)器,已接收到你發(fā)來(lái)的消息四啰!"
        server_socket.sendto(send_data.encode("gbk"), addr)

    # 關(guān)閉服務(wù)端套接字
    server_socket.close()

if __name__ == '__main__':
    main()

udp客戶端

img
import socket

# 定義要連接的服務(wù)端地址
HOST = ""
PORT = 7890
ADDR = (HOST, PORT)

def main():

    # 定義客戶端套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 通信循環(huán):收發(fā)消息
    while True:
        # 客戶端先發(fā)送消息
        send_data = input("請(qǐng)輸入要發(fā)送的數(shù)據(jù):")

        if not send_data:
            break

        client_socket.sendto(send_data.encode("gbk"), ADDR)

        recv_data, addr = client_socket.recvfrom(1024)

        # 打印服務(wù)器發(fā)過(guò)來(lái)的數(shù)據(jù)
        print(recv_data.decode("gbk"))

    # 關(guān)閉客戶端套接字
    client_socket.close()

if __name__ == '__main__':
    main()
2.3 tcp套接字

tcp通信模型

img

TCP服務(wù)器

偽代碼:

img

server_socket.accept方法:

  • tmp_socket, addr = server_socket.accept()
  • 該方法返回兩個(gè)數(shù)據(jù)宁玫,第一個(gè)為一個(gè)臨時(shí)的套接字用于標(biāo)記當(dāng)前連接的客戶端及用來(lái)與客戶端進(jìn)行通信;第二個(gè)為當(dāng)前連接客戶端的地址信息(ip,port)
img
import socket

# 定義服務(wù)器地址:主機(jī)名/ip柑晒、端口號(hào)
Host = ''
PORT = 7890
ADDR = (Host, PORT)

def main():

    # 定義TCP套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 綁定地址
    server_socket.bind(ADDR)

    # 開始監(jiān)聽(變?yōu)楸粍?dòng))
    server_socket.listen(128)

    # 通信循環(huán):用來(lái)循環(huán)接受客戶端連接
    while True:

        # 接受客戶端連接
        tmp_socket, addr= server_socket.accept()  # 返回一個(gè)臨時(shí)套接字(用于客戶端通信)及客戶端的地址
        print("connect from :", addr)

        # 通信循環(huán):使用臨時(shí)套接字收發(fā)數(shù)據(jù)
        while True:
            recv_data = tmp_socket.recv(1024)

            if not recv_data:
                break

            print(recv_data.decode("gbk"))

            send_data = "我是一個(gè)TCP服務(wù)器E繁瘛!"
            tmp_socket.send(send_data.encode("gbk"))

        tmp_socket.close()  # 關(guān)閉臨時(shí)套接字

    server_socket.close()  # 關(guān)閉監(jiān)聽套接字


if __name__ == '__main__':
    main()

TCP客戶端

偽代碼:

img
img
import socket

# 定義要連接的服務(wù)器端地址
Host = ""
PORT = 7890
ADDR = (Host, PORT)

def main():

    # 定義tcp客戶端套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 連接tcp服務(wù)器
    client_socket.connect(ADDR)

    # 通信循環(huán):收發(fā)數(shù)據(jù)

    while True:

        send_data = input("請(qǐng)輸入要發(fā)送的數(shù)據(jù):")

        # 發(fā)送數(shù)據(jù)給服務(wù)器
        client_socket.send(send_data.encode("gbk"))

        # 從服務(wù)器接收數(shù)據(jù)并打印
        recv_data = client_socket.recv(1024)

        if not recv_data:
            break
        print(recv_data.decode("gbk"))

    client_socket.close()

if __name__ == '__main__':
    main()

tcp注意點(diǎn)

  • tcp服務(wù)器一般情況下都需要綁定匙赞,否則客戶端找不到這個(gè)服務(wù)器
  • tcp客戶端一般不綁定佛掖,因?yàn)槭侵鲃?dòng)鏈接服務(wù)器,所以只要確定好服務(wù)器的ip涌庭、port等信息就好芥被,本地客戶端可以隨機(jī)
  • tcp服務(wù)器中通過(guò)listen可以將socket創(chuàng)建出來(lái)的主動(dòng)套接字變?yōu)楸粍?dòng)的,這是做tcp服務(wù)器時(shí)必須要做的
  • 當(dāng)客戶端需要鏈接服務(wù)器時(shí)坐榆,就需要使用connect進(jìn)行鏈接拴魄,udp是不需要鏈接的而是直接發(fā)送,但是tcp必須先鏈接席镀,只有鏈接成功才能通信
  • 當(dāng)一個(gè)tcp客戶端連接服務(wù)器時(shí)匹中,服務(wù)器端會(huì)有1個(gè)新的套接字,這個(gè)套接字用來(lái)標(biāo)記這個(gè)客戶端豪诲,單獨(dú)為這個(gè)客戶端服務(wù)
  • listen后的套接字是被動(dòng)套接字顶捷,用來(lái)接收新的客戶端的鏈接請(qǐng)求的,而accept返回的新套接字是標(biāo)記這個(gè)新客戶端的
  • 關(guān)閉listen后的套接字意味著被動(dòng)套接字關(guān)閉了跛溉,會(huì)導(dǎo)致新的客戶端不能夠鏈接服務(wù)器焊切,但是之前已經(jīng)鏈接成功的客戶端正常通信扮授。
  • 關(guān)閉accept返回的套接字意味著這個(gè)客戶端已經(jīng)服務(wù)完畢
  • 當(dāng)客戶端的套接字調(diào)用close后,服務(wù)器端會(huì)recv解堵塞专肪,并且返回的長(zhǎng)度為0刹勃,因此服務(wù)器可以通過(guò)返回?cái)?shù)據(jù)的長(zhǎng)度來(lái)區(qū)別客戶端是否已經(jīng)下線

tcp的三次握手及四次揮手

img
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嚎尤,隨后出現(xiàn)的幾起案子荔仁,更是在濱河造成了極大的恐慌,老刑警劉巖芽死,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乏梁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡关贵,警方通過(guò)查閱死者的電腦和手機(jī)遇骑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)揖曾,“玉大人落萎,你說(shuō)我怎么就攤上這事√考簦” “怎么了练链?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)奴拦。 經(jīng)常有香客問(wèn)我媒鼓,道長(zhǎng),這世上最難降的妖魔是什么错妖? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任绿鸣,我火速辦了婚禮,結(jié)果婚禮上暂氯,老公的妹妹穿的比我還像新娘枚驻。我一直安慰自己,他們只是感情好株旷,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著尔邓,像睡著了一般晾剖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上梯嗽,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天齿尽,我揣著相機(jī)與錄音,去河邊找鬼灯节。 笑死循头,一個(gè)胖子當(dāng)著我的面吹牛绵估,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卡骂,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼国裳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了全跨?” 一聲冷哼從身側(cè)響起缝左,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎浓若,沒想到半個(gè)月后渺杉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挪钓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年是越,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碌上。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡倚评,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绍赛,到底是詐尸還是另有隱情蔓纠,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布吗蚌,位于F島的核電站腿倚,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蚯妇。R本人自食惡果不足惜敷燎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望箩言。 院中可真熱鬧硬贯,春花似錦、人聲如沸陨收。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)务漩。三九已至拄衰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饵骨,已是汗流浹背翘悉。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留居触,地道東北人妖混。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓老赤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親制市。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抬旺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容