最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中的Socket 與 ScoketServer 通信及遇到問題解決方法

 更新時間:2019年04月01日 10:40:42   作者:東小東  
Socket有一個緩沖區(qū),緩沖區(qū)是一個流,先進先出,發(fā)送和取出的可自定義大小的,如果取出的數(shù)據(jù)未取完緩沖區(qū),則可能存在數(shù)據(jù)怠慢。本文通過實例代碼給大家介紹Python中的Socket 與 ScoketServer 通信及遇到問題解決方法 ,需要的朋友參考下吧

Socket有一個緩沖區(qū),緩沖區(qū)是一個流,先進先出,發(fā)送和取出的可自定義大小的,如果取出的數(shù)據(jù)未取完緩沖區(qū),則可能存在數(shù)據(jù)怠慢。其中【recv(1024)】表示從緩沖區(qū)里取最大為1024個字節(jié),但實際取值大小是不確定的,推薦其值小于等于8192。

黏包問題:

Socket發(fā)送兩條連續(xù)數(shù)據(jù)時,可能最終會拼接成一條進行發(fā)送

解決方法一:

兩條數(shù)據(jù)間進行延時發(fā)送,如【tiem.sleep(0.5) #延時0.5s】

解決方法二:

每次發(fā)送后等待對方確認(rèn)接收信息數(shù)據(jù),發(fā)送一條后就立即接收等待

解決方法三:

設(shè)定接收數(shù)據(jù)大小,發(fā)送端每次發(fā)送需要發(fā)送的數(shù)據(jù)的數(shù)據(jù)大小,接收端通過設(shè)置【recv(xx)】只接收確定的大小

Socket基本使用:

簡單的服務(wù)器:

import socket
sser=socket.socket()#得到socket對象
sser.bind(("0.0.0.0",2699))#建立監(jiān)聽
sser.listen(3)
print("等等客戶端連接")
conn,addr=sser.accept() #等待連接,會一直處于阻塞,返回連接對象和對方地址
print("有客戶端已經(jīng)連接,IP地址和端口為:",addr)
#接收數(shù)據(jù),會一直阻塞,建議低于8192
#使用連接對象操作
rdata=conn.recv(1024)
print(rdata.decode("gbk"))
conn.send("服務(wù)器返回,收到數(shù)據(jù)".encode("gbk"))#發(fā)送數(shù)據(jù),使用連接對象操作
#關(guān)閉連接
sser.close()

簡單的客戶端:

import socket
sclient=socket.socket()#得到socket對象
#連接服務(wù)器
#失敗會報錯:ConnectionRefusedError
sclient.connect(("192.168.1.135",2699))
sclient.send("東小東".encode("gbk"))#發(fā)送數(shù)據(jù)
#接收數(shù)據(jù),會一直阻塞,建議低于8192
rdata=sclient.recv(1024)
print(rdata.decode("gbk"))
#關(guān)閉連接
sclient.close()

Soket進階:

服務(wù)器進階:

實現(xiàn)客戶循環(huán)連接及數(shù)據(jù)循環(huán)收發(fā)和判斷客戶端是否斷開

import socket
sser=socket.socket()#得到socket對象
sser.bind(("0.0.0.0",2699))#建立監(jiān)聽
sser.listen(3)
while True:
  print("等等客戶端連接")
  conn,addr=sser.accept() #等待連接,會一直處于阻塞,返回連接對象和對方地址
  print("有客戶端已經(jīng)連接,IP地址和端口為:",addr)
  conn.send(("服務(wù)器歡迎你:%s\r\n"%(str(addr))).encode("gbk")) # 發(fā)送數(shù)據(jù),使用連接對象操作
  while True:
    #接收數(shù)據(jù),會一直阻塞
    #使用連接對象操作
    rdata=conn.recv(1024)
    if not rdata: break #判斷客戶端是否斷開,斷開則收到空數(shù)據(jù)
    print(rdata.decode("gbk"))
    conn.send("服務(wù)器返回,收到數(shù)據(jù)\r\n".encode("gbk"))#發(fā)送數(shù)據(jù),使用連接對象操作
#關(guān)閉連接
sser.close()

客戶端進階:

實現(xiàn)循環(huán)收發(fā)和判斷服務(wù)器是否斷開

import socket
sclient=socket.socket()#得到socket對象
#連接服務(wù)器
#失敗會報錯:ConnectionRefusedError
sclient.connect(("192.168.1.135",2699))
while True:
 #接收數(shù)據(jù),會一直阻塞
 rdata=sclient.recv(1024)
 if not rdata: break # 判斷服務(wù)器是否斷開,斷開則收到空數(shù)據(jù)
 print(rdata.decode("gbk"))
 sclient.send(("客戶端收到數(shù)據(jù):%s\r\n"%rdata.decode("gbk")).encode("gbk")) # 發(fā)送數(shù)據(jù)
#關(guān)閉連接
sclient.close()

注意:

發(fā)送數(shù)據(jù)不可發(fā)送空字符,否則會卡住,解決方法為判斷輸入的是否為空值,空值則進行數(shù)據(jù)發(fā)送

strx=input("輸入:").strip()#得到控制臺輸入值
if(len(strx)==0):continue #如果為空字符,則跳出本次循環(huán)
print(strx) #打印
sclient.send(strx.encode("gbk")) # 發(fā)送數(shù)據(jù)

發(fā)送大數(shù)據(jù):

先發(fā)送總體數(shù)據(jù)大小,socket另一端判斷實際接收的數(shù)據(jù)大小與總數(shù)據(jù)大小進行比較,循環(huán)recv()進行數(shù)據(jù)接收

 簡單的ssh實現(xiàn):

服務(wù)端:

import os
import socket
sser=socket.socket()#得到socket對象
sser.bind(("0.0.0.0",2697))#建立監(jiān)聽
sser.listen(3)
while True:
  print("等等客戶端連接")
  conn,addr=sser.accept() #等待連接,會一直處于阻塞,返回連接對象和對方地址
  print("有客戶端已經(jīng)連接,IP地址和端口為:",addr)
  conn.send(("服務(wù)器歡迎你:%s\r\n"%(str(addr))).encode("gbk")) # 發(fā)送數(shù)據(jù),使用連接對象操作
  while True:
    #接收數(shù)據(jù),會一直阻塞
    rdata=conn.recv(1024)
    if not rdata: break #判斷客戶端是否斷開,斷開則收到空數(shù)據(jù)
    sendtox=os.popen(rdata.decode("gbk")).read() #執(zhí)行命令
    conn.send(str(len(sendtox)).encode("gbk")) #發(fā)送執(zhí)行命令的結(jié)果長度
    #如果長度大于0 則發(fā)送命令結(jié)果數(shù)據(jù)
    if len(sendtox)>0:
    if conn.recv(10).decode("gbk")=="1":
     conn.sendall(sendtox.encode("gbk"))#發(fā)送最終數(shù)據(jù)
#關(guān)閉連接
sser.close()

客戶端:

import socket
sclient=socket.socket()#得到socket對象
#連接服務(wù)器
#失敗會報錯:ConnectionRefusedError
sclient.connect(("192.168.43.21",2697))
# 接收數(shù)據(jù),會一直阻塞
rdata = sclient.recv(1024)
print(rdata.decode("gbk"))
while True:
 strx = input("請輸入命令:").strip() # 得到控制臺輸入值
 if (len(strx) == 0): continue # 如果為空字符,則跳出本次循環(huán)
 sclient.send(strx.encode("gbk")) # 發(fā)送數(shù)據(jù)
 rdata = sclient.recv(10)
 if not rdata: break # 判斷服務(wù)器是否斷開,斷開則收到空數(shù)據(jù)
 #判斷命令是否執(zhí)行成功,0為失敗
 dataall=int(rdata.decode("gbk"))
 if dataall==0:
  continue
 sclient.send("1".encode("gbk")) # 發(fā)送確認(rèn)接收數(shù)據(jù)命令
 #循環(huán)接收數(shù)據(jù)
 datanew=0
 while dataall !=datanew:
  rdata=sclient.recv(1024).decode("gbk")
  datanew+=len(rdata)
  print(rdata)
#關(guān)閉連接
sclient.close()

發(fā)送文件:

發(fā)送文件,使用read()讀取文件數(shù)據(jù)后,可循環(huán)調(diào)用send()發(fā)送數(shù)據(jù),或者使用sendall()一次性發(fā)送所有數(shù)據(jù),socket另一端接收可循環(huán)recv()進行數(shù)據(jù)接收,且每次接收的數(shù)據(jù)大小是不確定的。文件傳輸需要驗證發(fā)送和接受的數(shù)據(jù)是否完全一致,可以通過數(shù)據(jù)大小加md5雙重驗證,發(fā)送端:md5在每次發(fā)送一條數(shù)據(jù)時進行update(),在數(shù)據(jù)發(fā)送完成后再發(fā)送md5值;接受端:md5在每次接收到一條數(shù)據(jù)后進行update(),在文件接收完成后再接收發(fā)送端發(fā)送的md5值,將兩值進行比較,相同則表示傳輸無丟包,但加入md5校驗,將會影響傳輸速率。

發(fā)送文件數(shù)據(jù):先發(fā)送總體數(shù)據(jù)大小,socket另一端判斷實際接收的數(shù)據(jù)大小與總數(shù)據(jù)大小進行比較,循環(huán)recv()進行數(shù)據(jù)接收

示例:客戶端發(fā)送文件名,服務(wù)器判斷文件是否存在,如果不存在或者是空文件則不進行傳輸,服務(wù)器進行文件發(fā)送,客戶端實現(xiàn)文件接收

服務(wù)器

import os
import socket
sser=socket.socket()#得到socket對象
sser.bind(("0.0.0.0",2697))#建立監(jiān)聽
sser.listen(3)
while True:
  print("等等客戶端連接")
  conn,addr=sser.accept() #等待連接,會一直處于阻塞,返回連接對象和對方地址
  print("有客戶端已經(jīng)連接,IP地址和端口為:",addr)
  conn.send(("服務(wù)器歡迎你:%s\r\n"%(str(addr))).encode("gbk")) # 發(fā)送數(shù)據(jù),使用連接對象操作
  while True:
    #接收數(shù)據(jù),會一直阻塞
    rdata=conn.recv(1024)
    if not rdata: break #判斷客戶端是否斷開,斷開則收到空數(shù)據(jù)
    filesize=0
    filenamex=rdata.decode("gbk")
    if os.path.isfile(filenamex): #判斷是否是文件
     filesize=os.stat(filenamex).st_size #得到文件大小
    conn.send(str(filesize).encode("gbk")) #不是文件則發(fā)送0,是文件則是實際大小
    #如果文件大小大于0 則發(fā)送文件
    if filesize>0:
    if conn.recv(10).decode("gbk")=="1": #等待確認(rèn)接收命令
     #一行一行發(fā)送數(shù)據(jù)
     f=open(filenamex,"rb")
     for linex in f:
      conn.sendall(linex)#發(fā)送最終數(shù)據(jù)
#關(guān)閉連接
sser.close()

客戶端

import socket
sclient=socket.socket()#得到socket對象
#連接服務(wù)器
#失敗會報錯:ConnectionRefusedError
sclient.connect(("192.168.43.21",2697))
# 接收數(shù)據(jù),會一直阻塞
rdata = sclient.recv(1024)
print(rdata.decode("gbk"))
while True:
 filenamex = input("請輸入文件名:").strip() # 得到控制臺輸入值
 if (len(filenamex) == 0): continue # 如果為空字符,則跳出本次循環(huán)
 sclient.send(filenamex.encode("gbk")) # 發(fā)送數(shù)據(jù)
 rdata = sclient.recv(10)
 if not rdata: break # 判斷服務(wù)器是否斷開,斷開則收到空數(shù)據(jù)
 #判斷命令是否執(zhí)行成功,0為失敗
 dataall=int(rdata.decode("gbk"))
 if dataall==0:
  print("文件不存在或者為空")
  continue
 sclient.send("1".encode("gbk")) # 發(fā)送確認(rèn)接收數(shù)據(jù)命令
 #打開文件
 f=open(filenamex,"wb")
 #循環(huán)接收數(shù)據(jù)
 datanew=0
 while dataall !=datanew:
  rdata=sclient.recv(1024)
  datanew+=len(rdata)
  f.write(rdata)
 print("文件(%s)接收完畢"%filenamex)
 f.close() #關(guān)閉文件
#關(guān)閉連接
sclient.close()

ScoketServer

服務(wù)端實現(xiàn)多并發(fā)效果,可以同時接入多個客戶端

import socketserver
#建立一個類,必須繼承 socketserver.BaseRequestHandler 類
class DongSocket(socketserver.BaseRequestHandler):
 #必須重寫handle方法
 def handle(self):
  print("建立新連接,對方地址為:{}".format(self.client_address))
  while True:
   try:
    self.datax=self.request.recv(1024).decode("gbk") #接收數(shù)據(jù)
    print("接收的數(shù)據(jù)為:%s"%self.datax)
    self.request.send(("服務(wù)器返回數(shù)據(jù):%s"%self.datax).encode("gbk"))
   except Exception as e:
    print("斷開,再見:{}".format(self.client_address))
    break
#參數(shù):(("ip",端口),自定義類)
#ss=socketserver.TCPServer(("0.0.0.0",2351),DongSocket) #與之前的socket服務(wù)器效果一致,同時只能連接一個客戶端
ss=socketserver.ThreadingTCPServer(("0.0.0.0",2351),DongSocket) #同時可以連接多個客戶端,多并發(fā)
ss.serve_forever()

總結(jié)

以上所述是小編給大家介紹的Python中的Socket 與 ScoketServer 通信及遇到問題解決方法 ,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

最新評論

长乐市| 丹江口市| 鹿泉市| 图木舒克市| 财经| 拜城县| 合阳县| 伊宁市| 大兴区| 张掖市| 始兴县| 开江县| 朔州市| 北海市| 新晃| 云梦县| 南丰县| 嵊泗县| 五寨县| 定州市| 通许县| 琼结县| 珲春市| 墨江| 清水河县| 增城市| 嘉禾县| 尉犁县| 洮南市| 犍为县| 凤阳县| 武汉市| 泗阳县| 九龙坡区| 平湖市| 镇康县| 崇阳县| 界首市| 龙海市| 弥渡县| 西盟|