Python的socket與socketserver怎么使用_第1頁(yè)
Python的socket與socketserver怎么使用_第2頁(yè)
Python的socket與socketserver怎么使用_第3頁(yè)
Python的socket與socketserver怎么使用_第4頁(yè)
Python的socket與socketserver怎么使用_第5頁(yè)
已閱讀5頁(yè),還剩9頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第Python的socket與socketserver怎么使用#1、買(mǎi)手機(jī)

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#tcp稱為流式協(xié)議,udp稱為數(shù)據(jù)報(bào)協(xié)議SOCK_DGRAM

#print(phone)

#2、插入/綁定手機(jī)卡

#phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

phone.bind((127.0.0.1,8080))

#3、開(kāi)機(jī)

phone.listen(5)#半連接池,限制的是請(qǐng)求數(shù)

#4、等待電話連接

print(start....)

whileTrue:#連接循環(huán)

conn,client_addr=phone.accept()#(三次握手建立的雙向連接,(客戶端的ip,端口))

#print(conn)

print(已經(jīng)有一個(gè)連接建立成功,client_addr)

#5、通信:收\(chéng)發(fā)消息

whileTrue:#通信循環(huán)

print(服務(wù)端正在收數(shù)據(jù)...)

data=conn.recv(1024)#最大接收的字節(jié)數(shù),沒(méi)有數(shù)據(jù)會(huì)在原地一直等待收,即發(fā)送者發(fā)送的數(shù)據(jù)量必須0bytes

#print(===)

iflen(data)==0:break#在客戶端單方面斷開(kāi)連接,服務(wù)端才會(huì)出現(xiàn)收空數(shù)據(jù)的情況

print(來(lái)自客戶端的數(shù)據(jù),data)

conn.send(data.upper())

exceptConnectionResetError:

break

#6、掛掉電話連接

conn.close()

#7、關(guān)機(jī)

phone.close()

#start....

#已經(jīng)有一個(gè)連接建立成功(127.0.0.1,4065)

#服務(wù)端正在收數(shù)據(jù)...

#來(lái)自客戶端的數(shù)據(jù)b\xad

#服務(wù)端正在收數(shù)據(jù)...

2、客戶端

importsocket

#1、買(mǎi)手機(jī)

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

#print(phone)

#2、撥電話

phone.connect((127.0.0.1,8080))#指定服務(wù)端ip和端口

#3、通信:發(fā)\收消息

whileTrue:#通信循環(huán)

msg=input(:).strip()#msg=

iflen(msg)==0:continue

phone.send(msg.encode(utf-8))

#print(hassend-----)

data=phone.recv(1024)

#print(hasrecv-----)

print(data)

#4、關(guān)閉

phone.close()

#:啊

#ba

#:啊啊

#b\xb0\xa1\xb0\xa1

#:

3、地址占用問(wèn)題

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

1、方法一:加入一條socket配置,重用ip和端口

phone=socket(AF_INET,SOCK_STREAM)

phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)#就是它,在bind前加

phone.bind((127.0.0.1,8080))

2、方法二:通過(guò)調(diào)整linux內(nèi)核參數(shù)

發(fā)現(xiàn)系統(tǒng)存在大量TIME_WAIT狀態(tài)的連接,通過(guò)調(diào)整linux內(nèi)核參數(shù)解決,

vi/etc/sysctl.conf

編輯文件,加入以下內(nèi)容:

net.ipv4.tcp_syncookies=1

net.ipv4.tcp_tw_reuse=1

net.ipv4.tcp_tw_recycle=1

net.ipv4.tcp_fin_timeout=30

然后執(zhí)行/sbin/sysctl-p讓參數(shù)生效。

net.ipv4.tcp_syncookies=1表示開(kāi)啟SYNCookies。當(dāng)出現(xiàn)SYN等待隊(duì)列溢出時(shí),啟用cookies來(lái)處理,可防范少量SYN攻擊,默認(rèn)為0,表示關(guān)閉;

net.ipv4.tcp_tw_reuse=1表示開(kāi)啟重用。允許將TIME-WAITsockets重新用于新的TCP連接,默認(rèn)為0,表示關(guān)閉;

net.ipv4.tcp_tw_recycle=1表示開(kāi)啟TCP連接中TIME-WAITsockets的快速回收,默認(rèn)為0,表示關(guān)閉。

net.ipv4.tcp_fin_timeout修改系統(tǒng)默認(rèn)的TIMEOUT時(shí)間

4、模擬ssh遠(yuǎn)程執(zhí)行命令

服務(wù)端通過(guò)subprocess執(zhí)行該命令,然后返回命令的結(jié)果。

服務(wù)端:

fromsocketimport*

importsubprocess

server=socket(AF_INET,SOCK_STREAM)

server.bind((127.0.0.1,8000))

server.listen(5)

print(start...)

whileTrue:

conn,client_addr=server.accept()

whileTrue:

print(fromclient:,client_addr)

cmd=conn.recv(1024)

iflen(cmd)==0:break

print(cmd:,cmd)

obj=subprocess.Popen(cmd.decode(utf8),#輸入的cmd命令

shell=True,#通過(guò)shell運(yùn)行

stderr=subprocess.PIPE,#把錯(cuò)誤輸出放入管道,以便打印

stdout=subprocess.PIPE)#把正確輸出放入管道,以便打印

stdout=obj.stdout.read()#打印正確輸出

stderr=obj.stderr.read()#打印錯(cuò)誤輸出

conn.send(stdout)

conn.send(stderr)

conn.close()

server.close()

客戶端

importsocket

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

client.connect((127.0.0.1,8000))

whileTrue:

data=input(pleaseenteryourdata)

client.send(data.encode(utf8))

data=client.recv(1024)

print(fromserver:,data)

client.close()

輸入dir命令,由于服務(wù)端發(fā)送字節(jié)少于1024字節(jié),客戶端可以接受。

輸入tasklist命令,由于服務(wù)端發(fā)送字節(jié)多于1024字節(jié),客戶端只接受部分?jǐn)?shù)據(jù),并且當(dāng)你再次輸入dir命令的時(shí)候,客戶端會(huì)接收dir命令的結(jié)果,但是會(huì)打印上一次的剩余未發(fā)送完的數(shù)據(jù),這就是粘包問(wèn)題。

1、發(fā)送端需要等緩沖區(qū)滿才發(fā)送出去,造成粘包

發(fā)送數(shù)據(jù)時(shí)間間隔很短,數(shù)據(jù)量很小,會(huì)合到一起,產(chǎn)生粘包。

服務(wù)端

#_*_coding:utf-8_*_

fromsocketimport*

ip_port=(127.0.0.1,8080)

TCP_socket_server=socket(AF_INET,SOCK_STREAM)

TCP_socket_server.bind(ip_port)

TCP_socket_server.listen(5)

conn,addr=TCP_socket_server.accept()

data1=conn.recv(10)

data2=conn.recv(10)

print(-----,data1.decode(utf-8))

print(-----,data2.decode(utf-8))

conn.close()

客戶端

#_*_coding:utf-8_*_

importsocket

BUFSIZE=1024

ip_port=(127.0.0.1,8080)

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

res=s.connect_ex(ip_port)

s.send(hello.encode(utf-8))

s.send(world.encode(utf-8))

#服務(wù)端一起收到bhelloworld

2、接收方不及時(shí)接收緩沖區(qū)的包,造成多個(gè)包接收

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

服務(wù)端

#_*_coding:utf-8_*_

fromsocketimport*

ip_port=(127.0.0.1,8080)

TCP_socket_server=socket(AF_INET,SOCK_STREAM)

TCP_socket_server.bind(ip_port)

TCP_socket_server.listen(5)

conn,addr=TCP_socket_server.accept()

data1=conn.recv(2)#一次沒(méi)有收完整

data2=conn.recv(10)#下次收的時(shí)候,會(huì)先取舊的數(shù)據(jù),然后取新的

print(-----,data1.decode(utf-8))

print(-----,data2.decode(utf-8))

conn.close()

客戶端

#_*_coding:utf-8_*_

importsocket

BUFSIZE=1024

ip_port=(127.0.0.1,8080)

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

res=s.connect_ex(ip_port)

s.send(hellofeng.encode(utf-8))

6、解決粘包問(wèn)題

1、先發(fā)送的字節(jié)流總大小(low版)

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

為何low:程序的運(yùn)行速度遠(yuǎn)快于網(wǎng)絡(luò)傳輸速度,所以在發(fā)送一段字節(jié)前,先用send去發(fā)送該字節(jié)流長(zhǎng)度,這種方式會(huì)放大網(wǎng)絡(luò)延遲帶來(lái)的性能損耗。

服務(wù)端:

importsocket,subprocess

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

server.bind((127.0.0.1,8000))

server.listen(5)

whileTrue:

conn,addr=server.accept()

print(start...)

whileTrue:

cmd=conn.recv(1024)

print(cmd:,cmd)

obj=subprocess.Popen(cmd.decode(utf8),

shell=True,

stderr=subprocess.PIPE,

stdout=subprocess.PIPE)

stdout=obj.stdout.read()

ifstdout:

ret=stdout

else:

stderr=obj.stderr.read()

ret=stderr

ret_len=len(ret)

conn.send(str(ret_len).encode(utf8))

data=conn.recv(1024).decode(utf8)

ifdata==recv_ready:

conn.sendall(ret)

conn.close()

server.close()

客戶端:

importsocket

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

client.connect((127.0.0.1,8000))

whileTrue:

msg=input(pleaseenteryourcmdyouwant).strip()

iflen(msg)==0:continue

client.send(msg.encode(utf8))

length=int(client.recv(1024))

client.send(recv_ready.encode(utf8))

send_size=0

recv_size=0

data=b

whilerecv_sizelength:

data=client.recv(1024)

recv_size+=len(data)

print(data.decode(utf8))

2、自定義固定長(zhǎng)度報(bào)頭(struct模塊)

struct模塊解析

importstruct

importjson

#i是格式

obj=struct.pack(i,1222222222223)

exceptExceptionase:

print(e)

obj=struct.pack(i,1222)

print(obj,len(obj))

#iformatrequires-2147483648=number=2147483647

#b\xc6\x04\x00\x004

res=struct.unpack(i,obj)

print(res[0])

#1222

解決粘包問(wèn)題的核心就是:為字節(jié)流加上自定義固定長(zhǎng)度報(bào)頭,報(bào)頭中包含字節(jié)流長(zhǎng)度,然后一次send到對(duì)端,對(duì)端在接收時(shí),先從緩存中取出定長(zhǎng)的報(bào)頭,然后再取真實(shí)數(shù)據(jù)。

1、使用struct模塊創(chuàng)建報(bào)頭:

importjson

importstruct

header_dic={

filename:a.txt,

total_size:111111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222223131232,

hash:asdf123123x123213x

header_json=json.dumps(header_dic)

header_bytes=header_json.encode(utf-8)

print(len(header_bytes))#223

#i是格式

obj=struct.pack(i,len(header_bytes))

print(obj,len(obj))

#b\xdf\x00\x00\x004

res=struct.unpack(i,obj)

print(res[0])

#223

2、服務(wù)端:

fromsocketimport*

importsubprocess

importstruct

importjson

server=socket(AF_INET,SOCK_STREAM)

server.bind((127.0.0.1,8000))

server.listen(5)

print(start...)

whileTrue:

conn,client_addr=server.accept()

print(conn,client_addr)

whileTrue:

cmd=conn.recv(1024)

obj=subprocess.Popen(cmd.decode(utf8),

shell=True,

stderr=subprocess.PIPE,

stdout=subprocess.PIPE)

stderr=obj.stderr.read()

stdout=obj.stdout.read()

#制作報(bào)頭

header_dict={

filename:a.txt,

total_size:len(stdout)+len(stderr),

hash:xasf123213123

header_json=json.dumps(header_dict)

header_bytes=header_json.encode(utf8)

#1.先把報(bào)頭的長(zhǎng)度len(header_bytes)打包成4個(gè)bytes,然后發(fā)送

conn.send(struct.pack(i,len(hea

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論