5.2黑客成長日記——socket-1

reference

1.0 黑客成長日記
2.0入門網(wǎng)絡(luò)工具
3.0 工具合集
4.0知乎
5.0客戶端服務(wù)端

其實不黑客

Socket編程

Socket編程所牽涉的東西非常寬泛枢劝,調(diào)用各種編程語言對socket的TCP(TCP可靠通信的實現(xiàn)方式)和UDP封裝進行網(wǎng)絡(luò)通信袍祖,可以是監(jiān)聽外部鏈接,也可以是主動發(fā)起鏈接請求伶选,發(fā)送特定協(xié)議并進行通信冤荆,如何制定協(xié)議規(guī)范玷过,如何進行協(xié)議的編碼和解碼人乓,如何將協(xié)議數(shù)據(jù)轉(zhuǎn)換為二進制數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)上和從網(wǎng)絡(luò)接收辨別且處理成功(牽涉到TCP粘包等問題),如何針對建立的鏈接進行管理等乳附。内地。。赋除。

前置知識:

1. 什么是socket
IP+端口阱缓,socket編程就是承載通訊的系統(tǒng)資源標(biāo)識
白話Socket 就是插座 端口就是插座上的孔 端口不能被其他進程占用 抽象理解 Socket 類似于操作某個IP地址上的某個端口達到點對點通信的目的, 需要綁定到某個具體的進程中和端口中。

2.TCP/IP四層協(xié)議

1.jpg

3.半相關(guān):網(wǎng)絡(luò)中用一個三元組可以在全局唯一標(biāo)志一個進程:
(協(xié)議举农,本地地址荆针,本地端口號)

4.全相關(guān)五元組:一個完整的網(wǎng)間進程通信需要兩個進程,同一種協(xié)議
(協(xié)議颁糟,本地地址航背,本地端口號,遠地地址棱貌,遠地端口號)

開始有點硬核起來:客戶端編程

socket類提供標(biāo)準(zhǔn)的BSD Socket API玖媚。
為了方便網(wǎng)絡(luò)服務(wù)器的開發(fā),**socketserver **為服務(wù)器端編程提供了進一步封裝
調(diào)用socket.socket可以創(chuàng)建一個Socket實例婚脱,socket類構(gòu)造函數(shù)聲明如下:

socket(family, type[,protocal])
我們看到socket構(gòu)造函數(shù)接收三個參數(shù)今魔,第一個為family勺像。family表示套接字對象使用的地址族,可選值:AF_INET——IPv4地址族错森,AF_INET6——IPv6地址族吟宦,AF_UNIX——針對類UNIX系統(tǒng)的套接字。第二個為type涩维,可使用的類型如下:socket.SOCK_STREAM基于TCP的流式socket通信
socket.SOCK_DGRAM基于UDP的數(shù)據(jù)報式socket通信

# -*- coding: UTF-8 -*-
import socket
import sys

#測試類
class Client:
    def __init__(self, host, ip=None, port=80):
        self.host = host #待連接的遠程主機的域名
        self.ip = ip
        self.port = port
    #
    #
    def connet_test(self): #連接方法
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            print("TCP connet")
        except socket.error as e:
            print("Failed to create socket. Error: %s"%e)
        sys.exit() #退出進程
    #
    #
    def connet(self): #連接方法
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            print('socket created')
        except socket.error as e:
            print("Failed to create socket. Error: %s"%e)
            sys.exit() #退出進程
        try:
            remote_ip = self.ip or socket.gethostbyname(self.host)#根據(jù)域名獲取ip
            print("get domain by IP: ", remote_ip)
        except socket.gaierror as e:
            print('主機無法被解析:', e)
            sys.exit() #退出進程
        try:
            s.connect((remote_ip, self.port)) #連接
            print('socket連接成功')
            message = bytes("GET / HTTP/1.1\r\n\r\n", encoding="UTF-8")
            # message = b"GET / HTTP/1.1\r\n\r\n"
            s.sendall(message) #發(fā)送數(shù)據(jù)
            print('發(fā)送數(shù)據(jù)成功')
            reply = s.recv(4096) #接收數(shù)據(jù)
            # while True:
            #     reply = s.recv(4096)
            #     if reply:
            #         print(reply)
            #     else:
            #         s.close()
            #         break
            print(reply)
            s.close() #關(guān)閉連接
        except socket.error:
            print("socket error")
            print('發(fā)送數(shù)據(jù)失敗')
            sys.exit() #退出進程
        return reply

if __name__ == '__main__':
    cl = Client('www.baidu.com', '127.0.0.1', 8008)
    # cl = Client('www.woqunidaye.com')
    # cl = Client('www.baidu.com')
    reply = cl.connet()
    print(reply.decode('UTF-8'))

上面的代碼里殃姓,總共有三個try,第一個try激挪,新建socket.socket實例辰狡,構(gòu)造一個半相關(guān)(這個是我自己想的不一定對)锋叨,這里你把網(wǎng)給停了垄分,這一步依舊是能走通的。
第二個try娃磺,通過域名獲取ip薄湿,如果是一個沒用的域名,就獲取不到ip
第三個try偷卧,選擇要接通的端口豺瘤,這里是80,通過s.connect方法鏈接遠程主機听诸。連接建立后坐求,通過sendall發(fā)送數(shù)據(jù),recv接收數(shù)據(jù)晌梨。注意數(shù)據(jù)是二進制的(如果數(shù)據(jù)很多的時候需要使用send方法循環(huán)發(fā)送桥嗤,接收也一樣,數(shù)據(jù)很大或者不知道具體多大就需要循環(huán)接收仔蝌。)
ps: b"GET / HTTP/1.1\r\n\r\n"就是標(biāo)準(zhǔn)的HTTP 1.0的請求報文

while True:
    reply = s.recv(4096)
    if reply:
        print(reply)
    else:
        s.close()
        break

開始有點硬核起來:服務(wù)端編程


# -*- coding: UTF-8 -*-
import socket
import sys

class server:
    def __init__(self, ip, port):
        self.port=port
        self.ip=ip

    def start(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#創(chuàng)建socket
        try:
            s.bind((self.ip, self.port)) # 綁定
            # 把socket綁定到傳入的IP和端口上泛领,調(diào)用bind方法,傳入ip和端口號敛惊。
            s.listen(10)#監(jiān)聽
            print('socket正在監(jiān)聽')
            # 進入監(jiān)聽狀態(tài)渊鞋,listen方法接收一個參數(shù),用來指定可以同時掛起的連接數(shù)瞧挤。
            print("s.family", s.family)
            print('等待客戶端連接')
            conn, addr = s.accept() # 接收連接
            # accept方法會返回一個代表當(dāng)前鏈接的connection對象和客戶端的ip地址
            print('客戶端連接 ' + addr[0] + ':' + str(addr[1]))
            data = conn.recv(1024) # 接收數(shù)據(jù)
            print("客戶端數(shù)據(jù):%s" % data)
            conn.sendall(bytes("你好客戶端\n\r", encoding = "utf8")) # 發(fā)送數(shù)據(jù)
            # conn.sendall(bytes("你好客戶端\n\r", encoding = "utf8")) # 發(fā)送數(shù)據(jù)
            print("服務(wù)端消息發(fā)往客戶端成功")
            conn.close()#關(guān)閉連接
        except socket.error as e:
            print(e)
            sys.exit()
        # finally:
        #      s.close() #關(guān)閉服務(wù)端
        print("正常關(guān)閉服務(wù)器")
        s.close() #關(guān)閉服務(wù)端


if __name__ == '__main__':
    s = server('', 8008)
    s.start()

server類的start方法創(chuàng)建了一個簡單的服務(wù)端锡宋。和客戶端編程類似,首先創(chuàng)建一個socket對象特恬。隨后执俩,我們要把socket綁定到傳入的IP和端口上,調(diào)用bind方法鸵鸥,傳入ip和端口號奠滑。服務(wù)端不會主動連接其他主機丹皱,而是等待客戶端連接,這需要進入監(jiān)聽狀態(tài)宋税,listen方法接收一個參數(shù)摊崭,用來指定可以同時掛起的連接數(shù)。監(jiān)聽模式之后杰赛,如果有客戶端連接進來呢簸,如何接收連接呢?需要使用accept方法乏屯。accept方法會返回一個代表當(dāng)前鏈接的connection對象和客戶端的ip地址根时。接下來就可以使用conn對象來接收和發(fā)送數(shù)據(jù)了,最后調(diào)用conn.close()關(guān)閉和客戶端的連接辰晕。下面我們啟動服務(wù)端蛤迎,然后再命令行啟動nc,來連接服務(wù)端含友。

一個有趣的現(xiàn)象:在客戶端s.recv(4096)替裆,在服務(wù)器端s.recv(1024),答:顯然是自己設(shè)定的窘问,sb
ps:把基于TCP改成基于UDP的時候本地不支持辆童,不知道為啥,坑惠赫,待填
pps:cli能收到server的回復(fù)把鉴,可是馬上就報錯了, 不知道為啥,后面不知道為啥又不報錯了儿咱。庭砍。。

socket正在監(jiān)聽
s.family AddressFamily.AF_INET
等待客戶端連接
客戶端連接 127.0.0.1:13819
客戶端數(shù)據(jù):b'GET / HTTP/1.1\r\n\r\n'
服務(wù)端消息發(fā)往客戶端成功
[WinError 10022] 提供了一個無效的參數(shù)概疆。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逗威,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子岔冀,更是在濱河造成了極大的恐慌凯旭,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件使套,死亡現(xiàn)場離奇詭異罐呼,居然都是意外死亡,警方通過查閱死者的電腦和手機侦高,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門嫉柴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人奉呛,你說我怎么就攤上這事计螺『痪。” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵登馒,是天一觀的道長匙握。 經(jīng)常有香客問我,道長陈轿,這世上最難降的妖魔是什么圈纺? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮麦射,結(jié)果婚禮上蛾娶,老公的妹妹穿的比我還像新娘。我一直安慰自己潜秋,他們只是感情好蛔琅,可當(dāng)我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著半等,像睡著了一般揍愁。 火紅的嫁衣襯著肌膚如雪棕洋。 梳的紋絲不亂的頭發(fā)上最域,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天脉漏,我揣著相機與錄音,去河邊找鬼切距。 笑死,一個胖子當(dāng)著我的面吹牛惨远,可吹牛的內(nèi)容都是我干的谜悟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼北秽,長吁一口氣:“原來是場噩夢啊……” “哼葡幸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起贺氓,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蔚叨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辙培,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔑水,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年扬蕊,在試婚紗的時候發(fā)現(xiàn)自己被綠了搀别。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡尾抑,死狀恐怖歇父,靈堂內(nèi)的尸體忽然破棺而出蒂培,到底是詐尸還是另有隱情,我是刑警寧澤榜苫,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布毁渗,位于F島的核電站,受9級特大地震影響单刁,放射性物質(zhì)發(fā)生泄漏灸异。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一羔飞、第九天 我趴在偏房一處隱蔽的房頂上張望肺樟。 院中可真熱鬧,春花似錦逻淌、人聲如沸么伯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽田柔。三九已至,卻和暖如春骨望,著一層夾襖步出監(jiān)牢的瞬間硬爆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工擎鸠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缀磕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓劣光,卻偏偏與公主長得像袜蚕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子绢涡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,955評論 2 355

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