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

下載本文檔

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

文檔簡介

第Python的socket與socketserver怎么使用#1、買手機

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

#print(phone)

#2、插入/綁定手機卡

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

phone.bind((127.0.0.1,8080))

#3、開機

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

#4、等待電話連接

print(start....)

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

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

#print(conn)

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

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

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

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

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

#print(===)

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

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

conn.send(data.upper())

exceptConnectionResetError:

break

#6、掛掉電話連接

conn.close()

#7、關(guān)機

phone.close()

#start....

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

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

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

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

2、客戶端

importsocket

#1、買手機

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ù)端仍然存在四次揮手的time_wAIt狀態(tài)在占用地址(如果不懂,請深入研究1.tcp三次握手,四次揮手2.syn洪水攻擊3.服務(wù)器高并發(fā)情況下會有大量的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、方法二:通過調(diào)整linux內(nèi)核參數(shù)

發(fā)現(xiàn)系統(tǒng)存在大量TIME_WAIT狀態(tài)的連接,通過調(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表示開啟SYNCookies。當出現(xiàn)SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN攻擊,默認為0,表示關(guān)閉;

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

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

net.ipv4.tcp_fin_timeout修改系統(tǒng)默認的TIMEOUT時間

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

服務(wù)端通過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,#通過shell運行

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

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

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

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

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é),客戶端只接受部分數(shù)據(jù),并且當你再次輸入dir命令的時候,客戶端會接收dir命令的結(jié)果,但是會打印上一次的剩余未發(fā)送完的數(shù)據(jù),這就是粘包問題。

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

發(fā)送數(shù)據(jù)時間間隔很短,數(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(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、接收方不及時接收緩沖區(qū)的包,造成多個包接收

客戶端發(fā)送了一段數(shù)據(jù),服務(wù)端只收了一小部分,服務(wù)端下次再收的時候還是從緩沖區(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)#一次沒有收完整

data2=conn.recv(10)#下次收的時候,會先取舊的數(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、解決粘包問題

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

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

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

服務(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、自定義固定長度報頭(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

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

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

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()

#制作報頭

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.先把報頭的長度len(header_bytes)打包成4個bytes,然后發(fā)送

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

溫馨提示

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

評論

0/150

提交評論