代碼:python
例子1:socket tcp 通信shell
server端json
import socket
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
print(conn)
print(addr)
from_client_msg = conn.recv(1024)
print(from_client_msg)
conn.send(b"Hello it's me")
conn.close()
server.close()
client端併發
import socket
client = socket.socket()
client.connect(("127.0.0.1",8001))
client.send(b"Who are you")
from_server_msg = client.recv(1024)
print(from_server_msg)
例子2:socket udp 通信
server端
import socket
udp_server = socket.socket(type=socket.SOCK_DGRAM)
ip_port = ('127.0.0.1',8001)
udp_server.bind(ip_port)
msg,addr = udp_server.recvfrom(1024)
print("來自客戶端消息:",msg)
udp_server.sendto(b'I am udpserver',addr)
udp_server.close()
client端
import socket
udp_client = socket.socket(type=socket.SOCK_DGRAM)
server_ip_port = ("127.0.0.1",8001)
udp_client.sendto(b"I am udpclient",server_ip_port)
print(udp_client)
from_server_msg = udp_client.recvfrom(1024)
print("來自服務端",from_server_msg)
udp_client.close()
查看緩衝區大小
import socket
server = socket.socket()
size = server.getsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF) ps:查看發送緩衝區大小
print(size)
size1 = server.getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF) ps:查看接收緩衝區大小
print(size1)
例子3:Tcp 服務端和客戶端通訊
服務端
import socket
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
print(conn)
print(addr)
while 1:
from_client_msg = conn.recv(1024)
print("來自客戶端的信息:", from_client_msg.decode("utf-8"))
server_msg = input("服務端說:")
conn.send(server_msg.encode("utf-8"))
conn.close()
server.close()
客戶端一號
import socket
client_01 = socket.socket()
ip_port = ('127.0.0.1',8001)
client_01.connect(ip_port)
while 1:
client_msg = input("客戶端一號說:")
client_01.send(client_msg.encode("utf-8"))
from_server_msg = client_01.recv(1024)
print(from_server_msg.decode("utf-8"))
客戶端2號
import socket
clinet_02 = socket.socket()
ip_port = ("127.0.0.1",8001)
clinet_02.connect(ip_port)
while True:
clinet_02_msg = input("客戶端2號說: ")
clinet_02.send(clinet_02_msg.encode("utf-8"))
from_server_msg = clinet_02.recv(1024)
print(from_server_msg.decode("utf-8"))
ps:tcp一次只能鏈接一個client在這個例子裏面
例子4:多個udp客戶端和單個upd服務端通訊
服務端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
while 1:
from_client_msg,addr = server.recvfrom(1024)
print("客戶端說:",from_client_msg.decode("utf-8"))
server_msg = input("服務端說:")
server.sendto(server_msg.encode("utf-8"),addr)
客戶端01號說:
import socket
client_01 = socket.socket(socket.AF_INET,type=socket.SOCK_DGRAM)
ip_port = ("127.0.0.1",8001)
while 1:
client_01_say = input("客戶端一號說:")
client_01.sendto(client_01_say.encode("utf-8"),ip_port)
msg,addr = client_01.recvfrom(1024)
print("來自服務端的消息:",msg.decode("utf-8"),addr)
客戶端2號
import socket
client_02 = socket.socket(type=socket.SOCK_DGRAM)
ip_port = ("127.0.0.1",8001)
while 1:
msg = input("客戶端2號說:")
send_to_server = client_02.sendto(msg.encode("utf-8"),ip_port)
rev_from_server,addr = client_02.recvfrom(1024)
print(rev_from_server.decode("utf-8"))
ps:在這個例子中,upd客戶端均可以跟服務端通信,可是服務端須要回覆了上一個客戶端發來的消息才能收到第二個客戶端發來的消息
例5:模擬粘包1
服務端
import socket
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
print(conn)
print("-----------華麗麗的分割線—————————————")
print(addr)
from_msg_client01 = conn.recv(1024)
from_msg_client02 = conn.recv(1024)
print("from_msg_client01",from_msg_client01.decode("utf-8"))
print("from_msg_client02",from_msg_client02.decode("utf-8"))
conn.close()
server.close()
#server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 地址複用
客戶端
import socket
client = socket.socket()
ip_port = ("127.0.0.1",8001)
client.connect(ip_port)
client.send(b"dating")
client.send(b"girl")
打印結果
模擬粘包2socket
服務端tcp
import socket
import subprocess
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
from_client_msg = conn.recv(1024).decode("gbk")
sub_conn = subprocess.Popen(
from_client_msg,
shell = True,
stdout = subprocess.PIPE,
stderr=subprocess.PIPE
)
cmd_result = sub_conn.stdout.read()
conn.send(cmd_result)
客戶端
import socket
client = socket.socket()
ip_port = ("127.0.0.1",8001)
client.connect(ip_port)
while 1:
send_msg = input("請輸入指令:").strip()
client.send(send_msg.encode("gbk"))
from_server_msg = client.recv(1024)
print(from_server_msg.decode("gbk"))
ps:第二種粘包會形成結果混亂例如輸入ipconfig返回的信息不全,而後在輸入dir此時返回的信息是ipconfig的一部分和dir結果的一部分,再次輸入ipconfig此時返回的是dir的結果
例6:解決粘包問題方案一 struct模塊
經過strct模塊裏的pack和unpack來解決 首先計算數據的長度 而後經過pack打包成四個字節發送 而後在發送實際字節
服務端
import socket
import subprocess
import struct
server = socket.socket()
ip_port = ("127.0.0.1",8001)
server.bind(ip_port)
server.listen()
conn,addr = server.accept()
while 1:
from_client_msg = conn.recv(1024).decode("gbk")
sub_conn = subprocess.Popen(
from_client_msg,
shell = True,
stdout = subprocess.PIPE,
stderr=subprocess.PIPE
)
cmd_result = sub_conn.stdout.read()
len_bytes = struct.pack("i",len(cmd_result))
conn.send(len_bytes)
conn.send(cmd_result)
客戶端
import socket
import struct
client = socket.socket()
ip_port = ("127.0.0.1",8001)
client.connect(ip_port)
while 1:
send_msg = input("請輸入指令:").strip()
client.send(send_msg.encode("gbk"))
from_server_msg = client.recv(4)
a = struct.unpack('i',from_server_msg)[0]
from_server_msg1 = client.recv(a)
print(from_server_msg1.decode("gbk"))
解決粘包方法2:sendall循環
接收端不知道發送端將要傳送的字節流的長度,因此解決粘包的方法就是圍繞,如何讓發送端在發送數據前,把本身將要發送的字節流總大小讓接收端知曉
,而後接收端發一個確認消息給發送端,而後發送端再發送過來後面的真實內容,接收端再來一個死循環接收完全部數據。
server端
import socket,subprocess
ip_port=('127.0.0.1',8080)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(ip_port)
s.listen(5)
while True:
conn,addr=s.accept()
print('客戶端',addr)
while True:
msg=conn.recv(1024)
if not msg:break
res=subprocess.Popen(msg.decode('utf-8'),shell=True,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
err=res.stderr.read()
if err:
ret=err
else:
ret=res.stdout.read()
data_length=len(ret)
conn.send(str(data_length).encode('utf-8'))
data=conn.recv(1024).decode('utf-8')
print(data)
if data == 'recv_ready':
conn.sendall(ret)
conn.close()
客戶端:
import socket,time
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(('127.0.0.1',8080))
while True:
msg=input('>>: ').strip()
if len(msg) == 0:continue
if msg == 'quit':break
s.send(msg.encode('utf-8'))
length=int(s.recv(1024).decode('utf-8'))
s.send('recv_ready'.encode('utf-8'))
send_size=0
recv_size=0
data=b''
while recv_size < length:
data+=s.recv(1024)
recv_size+=len(data)
print(data.decode('gbk'))
例6:socketserver實現高併發
import socketserver
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
while 1:
from_client_msg = self.request.recv(1024) # conn
print(from_client_msg.decode('utf-8'))
msg = input('to_client_msg>>>')
self.request.send(msg.encode('utf-8'))
if __name__ == '__main__':
ip_port = ('127.0.0.1',8001)
server = socketserver.ThreadingTCPServer(ip_port,MyServer)
server.serve_forever()
ps:客戶端的正常寫就ok
例子7:ftp客戶端上傳文件到ftp服務端
服務端
import socket
import struct
import json
server = socket.socket()
bufsize = 1024
server.bind(("127.0.0.1",8090))
server.listen(5)
conn,addr = server.accept()
head_len = conn.recv(4) #第一次接受4個字節
head_len = struct.unpack("i",head_len)[0] #解包獲得的值是一個元組,因此要加索引取值
json_head = conn.recv(head_len).decode("utf-8") #反序列化
head = json.loads(json_head)
file_size = head['filesize'] #獲取長度
with open(head["filename"],'wb') as f:
while file_size:
if file_size >= bufsize:
content = conn.recv(bufsize)
f.write(content)
else:
content = conn.recv(bufsize)
f.write(content)
break
conn.close()
server.close()
客戶端
import osimport jsonimport socketimport structclient = socket.socket()client.connect(("127.0.0.1",8090))bufsize = 1024head = { 'filepath':r'G:\python_project\day07', 'filename':'ftp_test', 'filesize':None}file_path = os.path.join(head["filepath"],head["filename"]) #拼接文件和目錄filesize = os.path.getsize(file_path) #獲取文件的大小head["filesize"] = filesize #把文件大小的值寫到head字典裏面json_head = json.dumps(head) #序列化頭部信息bytes_head = json_head.encode("utf-8") #對頭部信息進行編碼操做print(json_head)print(bytes_head)head_len = len(bytes_head) #統計頭部信息的長度pack_len = struct.pack("i",head_len) #把頭部信息打包成4個字節print(head_len)print(pack_len)client.send(pack_len)client.send(bytes_head)with open(file_path,'rb') as f: while filesize: if filesize >= bufsize: content = f.read(bufsize) client.send(content) filesize -= bufsize else: content = f.read(filesize) client.send(content) breakclient.close()