socket補充:通信循環、鏈接循環、遠程操作及黏包現象

socket補充:通信循環、鏈接循環、遠程操作及黏包現象

socket通信循環

server端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind(('127.0.0.1',8080))phone.listen(5)conn, client_addr = phone.accept()
print(conn, client_addr, sep='\n')while 1:  # 循環收發消息try:from_client_data = conn.recv(1024)print(from_client_data.decode('utf-8'))conn.send(from_client_data + b'SB')except ConnectionResetError:breakconn.close()
phone.close()

client端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 買電話phone.connect(('127.0.0.1',8080))  # 與客戶端建立連接, 撥號while 1:  # 循環收發消息client_data = input('>>>')phone.send(client_data.encode('utf-8'))from_server_data = phone.recv(1024)print(from_server_data.decode('utf-8'))phone.close()  # 掛電話

socket通信鏈接循環

server端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.bind(('127.0.0.1',8080))phone.listen(5)while 1 : # 循環連接客戶端conn, client_addr = phone.accept()print(client_addr)while 1:try:from_client_data = conn.recv(1024)print(from_client_data.decode('utf-8'))conn.send(from_client_data + b'SB')except ConnectionResetError:breakconn.close()
phone.close()

服務端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 買電話phone.connect(('127.0.0.1',8080))  # 與客戶端建立連接, 撥號while 1:client_data = input('>>>')phone.send(client_data.encode('utf-8'))from_server_data = phone.recv(1024)print(from_server_data.decode('utf-8'))phone.close()  # 掛電話

socket遠程操作

import subprocessobj = subprocess.Popen('dir1',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)print(obj.stdout.read().decode('gbk'))  # 正確命令
print(obj.stderr.read().decode('gbk'))  # 錯誤命令

服務端:

import socket
import subprocess
phone = socket.socket()phone.bind(('127.0.0.1',8848))phone.listen(2)
# listen: 2 允許有兩個客戶端加到半鏈接池,超過兩個則會報錯while 1:conn,addr = phone.accept()  # 等待客戶端鏈接我,阻塞狀態中print(f'鏈接來了: {conn,addr}')while 1:try:from_client_data = conn.recv(1024)  # 最多接受1024字節if from_client_data.upper() == b'Q':print('客戶端正常退出聊天了')breakobj = subprocess.Popen(from_client_data.decode('utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)result = obj.stdout.read() + obj.stderr.read()conn.send(result)except ConnectionResetError:print('客戶端鏈接中斷了')breakconn.close()
phone.close()# shell: 命令解釋器,相當于調用cmd 執行指定的命令。
# stdout:正確結果丟到管道中。
# stderr:錯了丟到另一個管道中。
# windows操作系統的默認編碼是gbk編碼。

客戶端:

import socketphone = socket.socket()phone.connect(('127.0.0.1',8848))
while 1:to_server_data = input('>>>輸入q或者Q退出').strip().encode('utf-8')if not to_server_data:# 服務端如果接受到了空的內容,服務端就會一直阻塞中,所以無論哪一端發送內容時,都不能為空發送print('發送內容不能為空')continuephone.send(to_server_data)if to_server_data.upper() == b'Q':breakfrom_server_data = phone.recv(1024)  # 最多接受1024字節print(f'{from_server_data.decode("gbk")}')phone.close()

什么叫做黏包現象?為什么會出現黏包現象?

socket收發消息的原理

1729998-20190816152859172-18357743.png

應用程序所看到的數據是一個整體,或說是一個流(stream),一條消息有多少字節對應用程序是不可見的,因此TCP協議是面向流的協議,這也是容易出現粘包問題的原因。

而UDP是面向消息的協議,每個UDP段都是一條消息,應用程序必須以消息為單位提取數據,不能一次提取任意字節的數據,這一點和TCP是很不同的。怎樣定義消息呢?

可以認為對方一次性write/send的數據為一個消息,需要明白的是當對方send一條信息的時候,無論底層怎樣分段分片,TCP協議層會把構成整條消息的數據段排序完成后才呈現在內核緩沖區。

設置緩沖區的兩個好處:

  1. 暫時存儲一些數據.
  2. 緩沖區存在如果你的網絡波動,保證數據的收發穩定,勻速.

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

只有TCP有粘包現象,UDP永遠不會粘包

黏包的兩種情況:

1,接收方沒有及時接收緩沖區的包,造成多個包接收(客戶端發送了一段數據,服務端只收了一小部分,服務端下次再收的時候還是從緩沖區拿上次遺留的數據,產生粘包)

server端:

import socket
import subprocessphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.bind(('127.0.0.1', 8080))phone.listen(5)while 1:  # 循環連接客戶端conn, client_addr = phone.accept()print(client_addr)while 1:try:cmd = conn.recv(1024)ret = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)correct_msg = ret.stdout.read()error_msg = ret.stderr.read()conn.send(correct_msg + error_msg)except ConnectionResetError:breakconn.close()
phone.close()

client端:

import socketphone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # 買電話phone.connect(('127.0.0.1',8080))  # 與客戶端建立連接, 撥號while 1:cmd = input('>>>')phone.send(cmd.encode('utf-8'))from_server_data = phone.recv(1024)print(from_server_data.decode('gbk'))phone.close()

2、發送端需要等緩沖區滿才發送出去,造成粘包(發送數據時間間隔很短,數據也很小,會合到一起,產生粘包)

server端:

import socketphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.bind(('127.0.0.1', 8080))phone.listen(5)conn, client_addr = phone.accept()frist_data = conn.recv(1024)
print('1:',frist_data.decode('utf-8'))  # 1: helloworld
second_data = conn.recv(1024)
print('2:',second_data.decode('utf-8'))conn.close()
phone.close()

客戶端:

import socketphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  phone.connect(('127.0.0.1', 8080)) phone.send(b'hello')
phone.send(b'world')phone.close()  # 兩次返送信息時間間隔太短,數據小,造成服務端一次收取

如何解決黏包現象?

struct模塊

該模塊可以把一個類型,如數字,轉成固定長度的bytes

1729998-20190816152911745-450888539.jpg

import struct
# 將一個數字轉化成等長度的bytes類型。
ret = struct.pack('i', 183346)
print(ret, type(ret), len(ret))# 通過unpack反解回來
ret1 = struct.unpack('i',ret)[0]
print(ret1, type(ret1), len(ret1))# 但是通過struct 處理不能處理太大ret = struct.pack('l', 4323241232132324)
print(ret, type(ret), len(ret))  # 報錯

方案一:low版。

  問題的根源在于,接收端不知道發送端將要傳送的字節流的長度,所以解決粘包的方法就是圍繞,如何讓發送端在發送數據前,把自己將要發送的字節流總數按照固定字節發送給接收端后面跟上總數據,然后接收端先接收固定字節的總字節流,再來一個死循環接收完所有數據。

server端:

import socket
import subprocess
import struct
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)phone.bind(('127.0.0.1', 8080))phone.listen(5)while 1:conn, client_addr = phone.accept()print(client_addr)while 1:try:cmd = conn.recv(1024)ret = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)correct_msg = ret.stdout.read()error_msg = ret.stderr.read()# 1 制作固定報頭total_size = len(correct_msg) + len(error_msg)header = struct.pack('i', total_size)# 2 發送報頭conn.send(header)# 發送真實數據:conn.send(correct_msg)conn.send(error_msg)except ConnectionResetError:breakconn.close()
phone.close()

client端:

import socket
import struct
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)phone.connect(('127.0.0.1',8080))while 1:cmd = input('>>>').strip()if not cmd: continuephone.send(cmd.encode('utf-8'))# 1,接收固定報頭header = phone.recv(4)# 2,解析報頭total_size = struct.unpack('i', header)[0]# 3,根據報頭信息,接收真實數據recv_size = 0res = b''while recv_size < total_size:recv_data = phone.recv(1024)res += recv_datarecv_size += len(recv_data)print(res.decode('gbk'))phone.close()

轉載于:https://www.cnblogs.com/lifangzheng/p/11364213.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247134.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247134.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247134.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PCA的原理及MATLAB實現

相關文章 PCA的原理及MATLAB實現 UFLDL教程&#xff1a;Exercise:PCA in 2D & PCA and Whitening python-A comparison of various Robust PCA implementations &#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&a…

Java生鮮電商平臺-SpringCloud微服務架構中核心要點和實現原理

Java生鮮電商平臺-SpringCloud微服務架構中核心要點和實現原理 說明&#xff1a;Java生鮮電商平臺中&#xff0c;我們將進一步理解微服務架構的核心要點和實現原理&#xff0c;為讀者的實踐提供微服務的設計模式&#xff0c;以期讓微服務在讀者正在工作的項目中起到積極的作用。…

iOS中下載小文件

在iOS中通過網絡下載小文件比如小型圖片等資源&#xff0c;一般在子線程中將數據完全下載完畢&#xff0c;然后在調用block將下載的數據整個部分返回&#xff0c;或者采用同步返回下載數據。 一般采用以下兩種方式&#xff1a; &#xff08;1&#xff09;使用GCD將下載操作放…

iOS下載大文件原理解析一

iOS中下載大型文件&#xff0c;需要考慮到占用內存的大小與下載速度&#xff08;使用多線程&#xff09;&#xff0c;因此本文首先介紹一個原理性下載文件的DEMO。 在下載大型文件中&#xff0c;需要知道下載的進度因此需要使用代理模式&#xff0c;不斷的回調下載進度。 - (…

recv原理、高階版黏包解決方案、基于UDP的socket通信

recv原理、高階版黏包解決方案、基于UDP的socket通信 recv原理 源碼解釋&#xff1a; Receive up to buffersize bytes from the socket. 接收來自socket緩沖區的字節數據&#xff0c; For the optional flags argument, see the Unix manual. 對于這些設置的參數&#xff0c;可…

iOS中下載大型文件的原理解析二

在iOS中下載大型文件&#xff0c;需要使用NSURLConnection 的代理方法&#xff1a; (void)touchesBegan:(NSSet)touches withEvent:(UIEvent *)event { NSURL *url [NSURL URLWithString:”http://d.3987.com/fengj_141112/007.jpg“]; NSURLRequest *request [NSURLReque…

ASP.NET Core Web 應用程序開發期間部署到IIS自定義主機域名并附加到進程調試

想必大家之前在進行ASP.NET Web 應用程序開發期間都有用到過將我們的網站部署到IIS自定義主機域名并附加到進程進行調試。 那我們的ASP.NET Core Web 應用程序又是如何部署到我們的IIS上面進行調試的呢&#xff0c;接下來我們來簡單介紹下&#xff1a; 一、安裝IIS所需的Host擴…

iOS下載大型文件原理解析三

在下載大型文件過程中是可以取消下載的 - (IBAction)download:(UIButton *)sender { // 狀態取反 sender.selected !sender.isSelected; // 斷點續傳 // 斷點下載if (sender.selected) { // 繼續&#xff08;開始&#xff09;下載// 1.URLNSURL *url [NSURL URLWithStrin…

HTML文件上傳與下載

文件下載 傳統的文件下載有兩種方法&#xff1a; 使用<a/>標簽&#xff0c;href屬性直接連接到服務器的文件路徑window.location.href"url"這兩種方法效果一樣。但有個很大的問題&#xff0c;如果下載出現異常&#xff08;連接路徑失效、文件不存在、網絡問題等…

NSURLSession的應用

iOS7以后發布了NSURLSession用來替換NSURLConnection&#xff0c;NSURLSession使用方式有以下兩種&#xff1a; 1.block方式 &#xff08;1&#xff09;創建的步驟 獲取單例會話對象 創建URL對象 隱含創建request 創建NSURLSessionDataTask // 1.獲取會話對象 NSURLSess…

ASP.NET Core Web 應用程序系列(一)- 使用ASP.NET Core內置的IoC容器DI進行批量依賴注入(MVC當中應用)...

在正式進入主題之前我們來看下幾個概念&#xff1a; 一、依賴倒置 依賴倒置是編程五大原則之一&#xff0c;即&#xff1a; 1、上層模塊不應該依賴于下層模塊&#xff0c;它們共同依賴于一個抽象。 2、抽象不能依賴于具體&#xff0c;具體依賴于抽象。 其中上層就是指使用者&am…

iOS中XML解析

iOS中XML解析分為兩種實現方式&#xff1a;SAX與DOM SAX方式&#xff1a;主要是事件驅動的解析方式&#xff0c;是逐行讀取XML數據&#xff0c;不斷回調代理&#xff0c;告訴代理當前解析的元素開始或者結束。 DOM解析方式&#xff1a;是講整個XML數據全部讀入內存&#xff0…

蘋果電腦基本設置+Linux 命令+Android 實戰集錦

本文微信公眾號「AndroidTraveler」首發。 背景 大多數應屆畢業生在大學期間使用的比較多的是 windows 電腦&#xff0c;因此初入職場如果拿到一臺蘋果電腦&#xff0c;可能一時間不能夠很快的上手。基于此&#xff0c;這邊出了系列視頻&#xff0c;通過實際的演示讓沒使用過蘋…

iOS中POST請求

iOS中POST請求的發送需要使用NSMutableURLRequest可以設置URL request的頭字段&#xff0c;比如超時時間&#xff0c;請求類型&#xff1a;GET POST等一些關鍵頭字段&#xff1a; - (IBAction)login { // 1.用戶名 NSString *usernameText self.username.text; if (userna…

發送JSON數據給服務器

需要將JSON格式的數據傳送給服務器&#xff0c;注意需要設置&#xff1a; [request setValue:”application/json” forHTTPHeaderField:”Content-Type”]; Content-Type類型為&#xff1a;application/json // 1.URL NSURL *url [NSURL URLWithString:"http://localh…

Mac中AndroidStudio沒有找到Plugins的問題

我們在windows中都可以正常找到plugins 但是在Mac上AndroidStudio里 setting打開卻沒有plugins 正準備在Mac上搞一下flutter呢 我感覺智商受到了侮辱&#xff01; 這里其實是mac版本給我開了個玩笑 你可以按快捷鍵&#xff0c;你就可以找到 快捷鍵 command ‘,’ 沒錯就是comm…

進程和操作系統概述

進程和操作系統概述 進程的基礎 程序和進程&#xff1a; 程序是一對靜態的代碼文件 進程是一個正在運行著的程序&#xff0c;抽象概念 進程由操作系統操控調用交于CPU運行 操作系統 1.管理控制協調計算機硬件和軟件的關系 2.操作系統的作用&#xff1f; ? 第一個作用&#xff…

iOS手勢操作簡介(一)

iOS中能夠響應手勢操作的類必須要繼承自UIResponder&#xff0c;才能夠處理手勢響應操作。 默認繼承了UIResponder的類有&#xff1a;UIApplication UIViewController UIView都繼承自UIResponder. UIView是UIResponder的子類&#xff0c;可以實現下列4個方法處理不同的觸摸事…

iOS開發中手勢處理簡介(二)

iOS中手勢操作事件的產生于傳遞 發生觸摸事件后&#xff0c;系統會將該事件加入到一個由UIApplication管理的事件隊列中 UIApplication會從事件隊列中取出最前面的事件&#xff0c;并將事件分發下去以便處理&#xff0c;通常&#xff0c;先發送事件給應用程序的主窗口&#x…

對前端Jenkins自動化部署的研究

1. 安裝 安裝 Nginx 1.1去官網下直接下載&#xff0c;解壓縮 start nginx就可以使了&#xff0c;常用命令&#xff1a; start nginx # 啟動 nginx -s reload # 修改配置后重新加載生效 nginx -s reopen # 重新打開日志文件 nginx -t # 配置文件檢測是否正確 1.2 安裝Jenkins…