日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

day28 socket网络编程

發(fā)布時間:2024/7/5 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 day28 socket网络编程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

一? socket 套接字

二? 粘包問題

?

一? socket 套接字

1.1 為何學(xué)習(xí)socket一定要先學(xué)習(xí)互聯(lián)網(wǎng)協(xié)議:

1.首先:網(wǎng)絡(luò)編程目標就是教會你如何基于socket編程,來開發(fā)一款自己的C/S架構(gòu)軟件

2.其次:C/S架構(gòu)的軟件(軟件屬于應(yīng)用層)是基于網(wǎng)絡(luò)進行通信的

3.然后:網(wǎng)絡(luò)的核心即一堆協(xié)議,協(xié)議即標準,你想開發(fā)一款基于網(wǎng)絡(luò)通信的軟件,就必須遵循這些標準。

4.最后:從這些標準開始研究,開啟socket編程

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

1.2 socket層

在上圖中,我們沒有看到Socket,我們用下圖來繼續(xù)說明.?


?

1.3 socket是什么

Socket是應(yīng)用層與TCP/IP協(xié)議通信的中間軟件抽象層,它是一組接口。在設(shè)計模式中,Socket其實就是一個門面模式,它把復(fù)雜的TCP/IP協(xié)議族隱藏在Socket接口后面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數(shù)據(jù),以符合指定的協(xié)議。

所以,我們無需深入理解tcp/udp協(xié)議,socket已經(jīng)為我們封裝好了,我們只需要遵循socket的規(guī)定去編程,寫出的程序自然就是遵循tcp/udp標準的。

1.4? 套接字發(fā)展史及分類

套接字起源于 20 世紀 70 年代加利福尼亞大學(xué)伯克利分校版本的 Unix,即人們所說的 BSD Unix。 因此,有時人們也把套接字稱為“伯克利套接字”或“BSD 套接字”。一開始,套接字被設(shè)計用在同 一臺主機上多個應(yīng)用程序之間的通訊。這也被稱進程間通訊,或 IPC。套接字有兩種(或者稱為有兩個種族),分別是基于文件型的和基于網(wǎng)絡(luò)型的。?

基于文件類型的套接字家族

套接字家族的名字:AF_UNIX

unix一切皆文件,基于文件的套接字調(diào)用的就是底層的文件系統(tǒng)來取數(shù)據(jù),兩個套接字進程運行在同一機器,可以通過訪問同一個文件系統(tǒng)間接完成通信

基于網(wǎng)絡(luò)類型的套接字家族

套接字家族的名字:AF_INET

(還有AF_INET6被用于ipv6,還有一些其他的地址家族,不過,他們要么是只用于某個平臺,要么就是已經(jīng)被廢棄,或者是很少被使用,或者是根本沒有實現(xiàn),所有地址家族中,AF_INET是使用最廣泛的一個,python支持很多種地址家族,但是由于我們只關(guān)心網(wǎng)絡(luò)編程,所以大部分時候我么只使用AF_INET)

1.5 套接字工作流程

???????一個生活中的場景。你要打電話給一個朋友,先撥號,朋友聽到電話鈴聲后提起電話,這時你和你的朋友就建立起了連接,就可以講話了。等交流結(jié)束,掛斷電話結(jié)束此次交談。?生活中的場景就解釋了這工作原理。

? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖3 ? ? ??

先從服務(wù)器端說起。服務(wù)器端先初始化Socket,然后與端口綁定(bind),對端口進行監(jiān)聽(listen),調(diào)用accept阻塞,等待客戶端連接。在這時如果有個客戶端初始化一個Socket,然后連接服務(wù)器(connect),如果連接成功,這時客戶端與服務(wù)器端的連接就建立了。客戶端發(fā)送數(shù)據(jù)請求,服務(wù)器端接收請求并處理請求,然后把回應(yīng)數(shù)據(jù)發(fā)送給客戶端,客戶端讀取數(shù)據(jù),最后關(guān)閉連接,一次交互結(jié)束

socket()模塊函數(shù)用法

1 import socket2 socket.socket(socket_family,socket_type,protocal=0)3 socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默認值為 0。4 5 獲取tcp/ip套接字6 tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)7 8 獲取udp/ip套接字9 udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 10 11 由于 socket 模塊中有太多的屬性。我們在這里破例使用了'from module import *'語句。使用 'from socket import *',我們就把 socket 模塊里的所有屬性都帶到我們的命名空間里了,這樣能 大幅減短我們的代碼。 12 例如tcpSock = socket(AF_INET, SOCK_STREAM)

?

服務(wù)端套接字函數(shù)
s.bind() 綁定(主機,端口號)到套接字
s.listen() 開始TCP監(jiān)聽
s.accept() 被動接受TCP客戶的連接,(阻塞式)等待連接的到來

客戶端套接字函數(shù)
s.connect() 主動初始化TCP服務(wù)器連接
s.connect_ex() connect()函數(shù)的擴展版本,出錯時返回出錯碼,而不是拋出異常

公共用途的套接字函數(shù)
s.recv() 接收TCP數(shù)據(jù)
s.send() 發(fā)送TCP數(shù)據(jù)(send在待發(fā)送數(shù)據(jù)量大于己端緩存區(qū)剩余空間時,數(shù)據(jù)丟失,不會發(fā)完)
s.sendall() 發(fā)送完整的TCP數(shù)據(jù)(本質(zhì)就是循環(huán)調(diào)用send,sendall在待發(fā)送數(shù)據(jù)量大于己端緩存區(qū)剩余空間時,數(shù)據(jù)不丟失,循環(huán)調(diào)用send直到發(fā)完)
s.recvfrom() 接收UDP數(shù)據(jù)
s.sendto() 發(fā)送UDP數(shù)據(jù)
s.getpeername() 連接到當前套接字的遠端的地址
s.getsockname() 當前套接字的地址
s.getsockopt() 返回指定套接字的參數(shù)
s.setsockopt() 設(shè)置指定套接字的參數(shù)
s.close() 關(guān)閉套接字

面向鎖的套接字方法
s.setblocking() 設(shè)置套接字的阻塞與非阻塞模式
s.settimeout() 設(shè)置阻塞套接字操作的超時時間
s.gettimeout() 得到阻塞套接字操作的超時時間

面向文件的套接字的函數(shù)
s.fileno() 套接字的文件描述符
s.makefile() 創(chuàng)建一個與該套接字相關(guān)的文件

?讀者勿看:socket實驗推演流程

1.6 基于TCP的套接字

tcp是基于鏈接的,必須先啟動服務(wù)端,然后再啟動客戶端去鏈接服務(wù)端

tcp服務(wù)端

1 ss = socket() #創(chuàng)建服務(wù)器套接字 2 ss.bind() #把地址綁定到套接字 3 ss.listen() #監(jiān)聽鏈接 4 inf_loop: #服務(wù)器無限循環(huán) 5 cs = ss.accept() #接受客戶端鏈接 6 comm_loop: #通訊循環(huán) 7 cs.recv()/cs.send() #對話(接收與發(fā)送) 8 cs.close() #關(guān)閉客戶端套接字 9 ss.close() #關(guān)閉服務(wù)器套接字(可選)

?

tcp客戶端

1 cs = socket() # 創(chuàng)建客戶套接字 2 cs.connect() # 嘗試連接服務(wù)器 3 comm_loop: # 通訊循環(huán) 4 cs.send()/cs.recv() # 對話(發(fā)送/接收) 5 cs.close() # 關(guān)閉客戶套接字

?

?

socket通信流程與打電話流程類似,我們就以打電話為例來實現(xiàn)一個low版的套接字通信

?服務(wù)端 ?客戶端

加上鏈接循環(huán)與通信循環(huán)

#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' import socket ip_port=('127.0.0.1',8081)#電話卡 BUFSIZE=1024 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #買手機 s.bind(ip_port) #手機插卡 s.listen(5) #手機待機while True: #新增接收鏈接循環(huán),可以不停的接電話conn,addr=s.accept() #手機接電話# print(conn)# print(addr)print('接到來自%s的電話' %addr[0])while True: #新增通信循環(huán),可以不斷的通信,收發(fā)消息msg=conn.recv(BUFSIZE) #聽消息,聽話# if len(msg) == 0:break #如果不加,那么正在鏈接的客戶端突然斷開,recv便不再阻塞,死循環(huán)發(fā)生print(msg,type(msg))conn.send(msg.upper()) #發(fā)消息,說話conn.close() #掛電話s.close() #手機關(guān)機 ?客戶端改進版

?

問題:在重啟服務(wù)端時可能會遇到

這個是由于你的服務(wù)端仍然存在四次揮手的time_wait狀態(tài)在占用地址(如果不懂,請深入研究1.tcp三次握手,四次揮手 2.syn洪水攻擊 3.服務(wù)器高并發(fā)情況下會有大量的time_wait狀態(tài)的優(yōu)化方法)

解決方法:

?方法一 ?方法二 1.7?基于UDP的套接字

udp是無鏈接的,先啟動哪一端都不會報錯

udp服務(wù)端

1 ss = socket() #創(chuàng)建一個服務(wù)器的套接字 2 ss.bind() #綁定服務(wù)器套接字 3 inf_loop: #服務(wù)器無限循環(huán) 4 cs = ss.recvfrom()/ss.sendto() # 對話(接收與發(fā)送) 5 ss.close() # 關(guān)閉服務(wù)器套接字

?

udp客戶端

cs = socket() # 創(chuàng)建客戶套接字 comm_loop: # 通訊循環(huán)cs.sendto()/cs.recvfrom() # 對話(發(fā)送/接收) cs.close() # 關(guān)閉客戶套接字

?

udp套接字簡單示例

?udp服務(wù)端 ?udp客戶端

qq聊天(由于udp無連接,所以可以同時多個客戶端去跟服務(wù)端通信)

?udp服務(wù)端 ?udp客戶端1 ?udp客戶端2

服務(wù)端運行結(jié)果

客戶端1運行結(jié)果

客戶端2運行結(jié)果

時間服務(wù)器

?ntp服務(wù)端 ?ntp客戶端

九 粘包現(xiàn)象

讓我們基于tcp先制作一個遠程執(zhí)行命令的程序(1:執(zhí)行錯誤命令 2:執(zhí)行l(wèi)s 3:執(zhí)行ifconfig)

注意注意注意:

res=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)

的結(jié)果的編碼是以當前所在的系統(tǒng)為準的,如果是windows,那么res.stdout.read()讀出的就是GBK編碼的,在接收端需要用GBK解碼

且只能從管道里讀一次結(jié)果

注意:命令ls -l ; lllllll ; pwd 的結(jié)果是既有正確stdout結(jié)果,又有錯誤stderr結(jié)果

?服務(wù)端 ?客戶端

上述程序是基于tcp的socket,在運行時會發(fā)生粘包

?

讓我們再基于udp制作一個遠程執(zhí)行命令的程序

?服務(wù)端 ?客戶端

上述程序是基于udp的socket,在運行時永遠不會發(fā)生粘包

十 什么是粘包

須知:只有TCP有粘包現(xiàn)象,UDP永遠不會粘包,為何,且聽我娓娓道來

首先需要掌握一個socket收發(fā)消息的原理

?

發(fā)送端可以是一K一K地發(fā)送數(shù)據(jù),而接收端的應(yīng)用程序可以兩K兩K地提走數(shù)據(jù),當然也有可能一次提走3K或6K數(shù)據(jù),或者一次只提走幾個字節(jié)的數(shù)據(jù),也就是說,應(yīng)用程序所看到的數(shù)據(jù)是一個整體,或說是一個流(stream),一條消息有多少字節(jié)對應(yīng)用程序是不可見的,因此TCP協(xié)議是面向流的協(xié)議,這也是容易出現(xiàn)粘包問題的原因。而UDP是面向消息的協(xié)議,每個UDP段都是一條消息,應(yīng)用程序必須以消息為單位提取數(shù)據(jù),不能一次提取任意字節(jié)的數(shù)據(jù),這一點和TCP是很不同的。怎樣定義消息呢?可以認為對方一次性write/send的數(shù)據(jù)為一個消息,需要明白的是當對方send一條信息的時候,無論底層怎樣分段分片,TCP協(xié)議層會把構(gòu)成整條消息的數(shù)據(jù)段排序完成后才呈現(xiàn)在內(nèi)核緩沖區(qū)。

例如基于tcp的套接字客戶端往服務(wù)端上傳文件,發(fā)送時文件內(nèi)容是按照一段一段的字節(jié)流發(fā)送的,在接收方看了,根本不知道該文件的字節(jié)流從何處開始,在何處結(jié)束

所謂粘包問題主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節(jié)的數(shù)據(jù)所造成的。

此外,發(fā)送方引起的粘包是由TCP協(xié)議本身造成的,TCP為提高傳輸效率,發(fā)送方往往要收集到足夠多的數(shù)據(jù)后才發(fā)送一個TCP段。若連續(xù)幾次需要send的數(shù)據(jù)都很少,通常TCP會根據(jù)優(yōu)化算法把這些數(shù)據(jù)合成一個TCP段后一次發(fā)送出去,這樣接收方就收到了粘包數(shù)據(jù)。

  • TCP(transport control protocol,傳輸控制協(xié)議)是面向連接的,面向流的,提供高可靠性服務(wù)。收發(fā)兩端(客戶端和服務(wù)器端)都要有一一成對的socket,因此,發(fā)送端為了將多個發(fā)往接收端的包,更有效的發(fā)到對方,使用了優(yōu)化方法(Nagle算法),將多次間隔較小且數(shù)據(jù)量小的數(shù)據(jù),合并成一個大的數(shù)據(jù)塊,然后進行封包。這樣,接收端,就難于分辨出來了,必須提供科學(xué)的拆包機制。 即面向流的通信是無消息保護邊界的。
  • UDP(user datagram protocol,用戶數(shù)據(jù)報協(xié)議)是無連接的,面向消息的,提供高效率服務(wù)。不會使用塊的合并優(yōu)化算法,, 由于UDP支持的是一對多的模式,所以接收端的skbuff(套接字緩沖區(qū))采用了鏈式結(jié)構(gòu)來記錄每一個到達的UDP包,在每個UDP包中就有了消息頭(消息來源地址,端口等信息),這樣,對于接收端來說,就容易進行區(qū)分處理了。?即面向消息的通信是有消息保護邊界的。
  • tcp是基于數(shù)據(jù)流的,于是收發(fā)的消息不能為空,這就需要在客戶端和服務(wù)端都添加空消息的處理機制,防止程序卡住,而udp是基于數(shù)據(jù)報的,即便是你輸入的是空內(nèi)容(直接回車),那也不是空消息,udp協(xié)議會幫你封裝上消息頭,實驗略
  • udp的recvfrom是阻塞的,一個recvfrom(x)必須對唯一一個sendinto(y),收完了x個字節(jié)的數(shù)據(jù)就算完成,若是y>x數(shù)據(jù)就丟失,這意味著udp根本不會粘包,但是會丟數(shù)據(jù),不可靠

    tcp的協(xié)議數(shù)據(jù)不會丟,沒有收完包,下次接收,會繼續(xù)上次繼續(xù)接收,己端總是在收到ack時才會清除緩沖區(qū)內(nèi)容。數(shù)據(jù)是可靠的,但是會粘包。

    兩種情況下會發(fā)生粘包。

    發(fā)送端需要等緩沖區(qū)滿才發(fā)送出去,造成粘包(發(fā)送數(shù)據(jù)時間間隔很短,數(shù)據(jù)了很小,會合到一起,產(chǎn)生粘包)

    ?服務(wù)端 ?客戶端

    接收方不及時接收緩沖區(qū)的包,造成多個包接收(客戶端發(fā)送了一段數(shù)據(jù),服務(wù)端只收了一小部分,服務(wù)端下次再收的時候還是從緩沖區(qū)拿上次遺留的數(shù)據(jù),產(chǎn)生粘包)?

    ?服務(wù)端 ?客戶端

    ?

    拆包的發(fā)生情況

    當發(fā)送端緩沖區(qū)的長度大于網(wǎng)卡的MTU時,tcp會將這次發(fā)送的數(shù)據(jù)拆成幾個數(shù)據(jù)包發(fā)送出去。

    補充問題一:為何tcp是可靠傳輸,udp是不可靠傳輸

    基于tcp的數(shù)據(jù)傳輸請參考我的另一篇文章http://www.cnblogs.com/linhaifeng/articles/5937962.html,tcp在數(shù)據(jù)傳輸時,發(fā)送端先把數(shù)據(jù)發(fā)送到自己的緩存中,然后協(xié)議控制將緩存中的數(shù)據(jù)發(fā)往對端,對端返回一個ack=1,發(fā)送端則清理緩存中的數(shù)據(jù),對端返回ack=0,則重新發(fā)送數(shù)據(jù),所以tcp是可靠的

    而udp發(fā)送數(shù)據(jù),對端是不會返回確認信息的,因此不可靠

    補充問題二:send(字節(jié)流)和recv(1024)及sendall

    recv里指定的1024意思是從緩存里一次拿出1024個字節(jié)的數(shù)據(jù)

    send的字節(jié)流是先放入己端緩存,然后由協(xié)議控制將緩存內(nèi)容發(fā)往對端,如果待發(fā)送的字節(jié)流大小大于緩存剩余空間,那么數(shù)據(jù)丟失,用sendall就會循環(huán)調(diào)用send,數(shù)據(jù)不會丟失

    十一 解決粘包的low比處理方法

    問題的根源在于,接收端不知道發(fā)送端將要傳送的字節(jié)流的長度,所以解決粘包的方法就是圍繞,如何讓發(fā)送端在發(fā)送數(shù)據(jù)前,把自己將要發(fā)送的字節(jié)流總大小讓接收端知曉,然后接收端來一個死循環(huán)接收完所有數(shù)據(jù)

    low版本的解決方法

    ?服務(wù)端 ?客戶端

    為何low:

    程序的運行速度遠快于網(wǎng)絡(luò)傳輸速度,所以在發(fā)送一段字節(jié)前,先用send去發(fā)送該字節(jié)流長度,這種方式會放大網(wǎng)絡(luò)延遲帶來的性能損耗

    十二 峰哥解決粘包的方法

    為字節(jié)流加上自定義固定長度報頭,報頭中包含字節(jié)流長度,然后一次send到對端,對端在接收時,先從緩存中取出定長的報頭,然后再取真實數(shù)據(jù)

    struct模塊?

    該模塊可以把一個類型,如數(shù)字,轉(zhuǎn)成固定長度的bytes

    >>> struct.pack('i',1111111111111)

    。。。。。。。。。

    struct.error: 'i' format requires -2147483648 <= number <= 2147483647 #這個是范圍

    ?

    import json,struct #假設(shè)通過客戶端上傳1T:1073741824000的文件a.txt#為避免粘包,必須自定制報頭 header={'file_size':1073741824000,'file_name':'/a/b/c/d/e/a.txt','md5':'8f6fbf8347faa4924a76856701edb0f3'} #1T數(shù)據(jù),文件路徑和md5值#為了該報頭能傳送,需要序列化并且轉(zhuǎn)為bytes head_bytes=bytes(json.dumps(header),encoding='utf-8') #序列化并轉(zhuǎn)成bytes,用于傳輸#為了讓客戶端知道報頭的長度,用struck將報頭長度這個數(shù)字轉(zhuǎn)成固定長度:4個字節(jié) head_len_bytes=struct.pack('i',len(head_bytes)) #這4個字節(jié)里只包含了一個數(shù)字,該數(shù)字是報頭的長度#客戶端開始發(fā)送 conn.send(head_len_bytes) #先發(fā)報頭的長度,4個bytes conn.send(head_bytes) #再發(fā)報頭的字節(jié)格式 conn.sendall(文件內(nèi)容) #然后發(fā)真實內(nèi)容的字節(jié)格式#服務(wù)端開始接收 head_len_bytes=s.recv(4) #先收報頭4個bytes,得到報頭長度的字節(jié)格式 x=struct.unpack('i',head_len_bytes)[0] #提取報頭的長度head_bytes=s.recv(x) #按照報頭長度x,收取報頭的bytes格式 header=json.loads(json.dumps(header)) #提取報頭#最后根據(jù)報頭的內(nèi)容提取真實的數(shù)據(jù),比如 real_data_len=s.recv(header['file_size']) s.recv(real_data_len) ?關(guān)于struct的詳細用法

    ?

    ?服務(wù)端(自定制報頭) ?客戶端(自定制報頭)

    我們可以把報頭做成字典,字典里包含將要發(fā)送的真實數(shù)據(jù)的詳細信息,然后json序列化,然后用struck將序列化后的數(shù)據(jù)長度打包成4個字節(jié)(4個自己足夠用了)

    發(fā)送時:

    先發(fā)報頭長度

    再編碼報頭內(nèi)容然后發(fā)送

    最后發(fā)真實內(nèi)容

    ?

    接收時:

    先手報頭長度,用struct取出來

    根據(jù)取出的長度收取報頭內(nèi)容,然后解碼,反序列化

    從反序列化的結(jié)果中取出待取數(shù)據(jù)的詳細信息,然后去取真實的數(shù)據(jù)內(nèi)容

    ?服務(wù)端:定制稍微復(fù)雜一點的報頭 ?客戶端

    ?

    ?

    FTP作業(yè):上傳下載文件

    ?服務(wù)端 import socket import struct import json import osclass MYTCPClient:address_family = socket.AF_INETsocket_type = socket.SOCK_STREAMallow_reuse_address = Falsemax_packet_size = 8192coding='utf-8'request_queue_size = 5def __init__(self, server_address, connect=True):self.server_address=server_addressself.socket = socket.socket(self.address_family,self.socket_type)if connect:try:self.client_connect()except:self.client_close()raisedef client_connect(self):self.socket.connect(self.server_address)def client_close(self):self.socket.close()def run(self):while True:inp=input(">>: ").strip()if not inp:continuel=inp.split()cmd=l[0]if hasattr(self,cmd):func=getattr(self,cmd)func(l)def put(self,args):cmd=args[0]filename=args[1]if not os.path.isfile(filename):print('file:%s is not exists' %filename)returnelse:filesize=os.path.getsize(filename)head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}print(head_dic)head_json=json.dumps(head_dic)head_json_bytes=bytes(head_json,encoding=self.coding)head_struct=struct.pack('i',len(head_json_bytes))self.socket.send(head_struct)self.socket.send(head_json_bytes)send_size=0with open(filename,'rb') as f:for line in f:self.socket.send(line)send_size+=len(line)print(send_size)else:print('upload successful')client=MYTCPClient(('127.0.0.1',8080))client.run()





    Socket(套接字)

    127.0.0.1本機回還地址
    只能自己識別自己 其他人無法訪問

    send與recv對應(yīng)
    不要出現(xiàn)兩邊都是相同的情況

    recv是跟內(nèi)存要數(shù)據(jù)
    至于數(shù)據(jù)的來源 你無需考慮

    TCP特點
    會將數(shù)據(jù)量比較小的并且時間間隔比較短的數(shù)據(jù)
    一次性打包發(fā)送給對方

    socket最簡單版本


    解決粘包問題的最復(fù)雜版本

    from socket import SOL_SOCKET,SO_REUSEADDR
    sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加

    解決粘包問題
    服務(wù)端
    1.先制作一個發(fā)送給客戶端的字典
    2.制作字典的報頭
    3.發(fā)送字典的報頭
    4.發(fā)送字典
    5.再發(fā)真實數(shù)據(jù)

    客戶端
    1.先接受字典的報頭
    2.解析拿到字典的數(shù)據(jù)長度
    3.接受字典
    4.從字典中獲取真實數(shù)據(jù)的長度
    5.接受真實數(shù)據(jù)

    寫一個上傳電影的功能
    1.循環(huán)打印某一個文件夾下面的所有的文件
    2.用戶選取想要上傳的文件
    3.將用戶選擇的文件上傳到服務(wù)端
    4.服務(wù)端保存該文件




    1.直接獲取數(shù)據(jù)1024
    2.制作一個數(shù)據(jù)的報頭
    3.先發(fā)個字典 然后再發(fā)真實數(shù)據(jù)

    ?
































    轉(zhuǎn)載于:https://www.cnblogs.com/Ryan-Yuan/p/11317724.html

    總結(jié)

    以上是生活随笔為你收集整理的day28 socket网络编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。