python-socket编程

TCP协议
一、简易版本
1、服务端
import socket
from socket import SOL_SOCKET, SO_REUSEADDR
new_socket = socket.socket()
new_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
new_socket.bind(('127.0.0.1', 8082))
new_socket.listen(5) --》mac本和linux本可以不写,本质是设置等待的客户的数量
conn, addr = new_socket.accept()
data=conn.rcve(1024)
conn.send(data.upper())
conn.close()
2、客户端
import socket
new_socket = socket.socket()
new_socket.connect(('127.0.0.1', 8082))
new_socket.send(b'judyjudy')
data=new_socket.rcve(1024)
print(data.decode('utf8'))
conn.close()
二、解决通道循环和通信循环以及优化
1、服务端
import socket
from socket import SOL_SOCKET, SO_REUSEADDR
new_socket = socket.socket()
new_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
#解决mac本端口占用问题
new_socket.bind(('127.0.0.1', 8082))
new_socket.listen(5) --》mac本和linux本可以不写
while True:
conn, addr = new_socket.accept()
while True:
data=conn.rcve(1024)
conn.send(data.upper())
2、客户端
import socket
new_socket = socket.socket()
new_socket.connect(('127.0.0.1', 8082))
while True:
data=input('please say something--->:').strip()
if len(data)==0: #客户端发送数据不能为空
continue
new_socket.send(data)
data_=new_socket.rcve(1024)
print(data_.decode('utf8'))
三、解决粘包问题
1、服务端
import socket
import subprocess
import struct
import json
from socket import SOL_SOCKET, SO_REUSEADDR
new_socket = socket.socket()
new_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
new_socket.bind(('127.0.0.1', 8082))
new_socket.listen()
while True:
conn, addr = new_socket.accept()
while True:
cmd = conn.recv(1024)
cmd = cmd.decode('utf8')
res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
res1 = res.stdout.read() + res.stdout.read()
d = {'filename': 'judyjudy', 'file_size': len(res1), 'btw': 'enjoy!!!!'}
d_json = json.dumps(d)
d_size = struct.pack('i', len(d_json))
conn.send(d_size)
conn.send(d_json.encode('utf8'))
conn.send(res1)
2、客户端
import socket
import struct
import json
new_socket = socket.socket()
new_socket.connect(('127.0.0.1', 8082))
while True:
cmd = input('请输入您的指令>>>>>:')
if len(cmd) == 0:
continue
new_socket.send(cmd.encode('utf8'))
data = new_socket.recv(4)
dic_length = struct.unpack('i', data)[0]
dic_json = new_socket.recv(dic_length)
dic_real = json.loads(dic_json)
print(dic_real)
file_real_length = dic_real['file_size']
data_real=new_socket.recv(file_real_length)
print(data_real.decode('gbk'))
四、上传或者下载数据
1、服务端
import socket
import os
import struct
import json
from socket import SOL_SOCKET, SO_REUSEADDR
new_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
new_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
new_socket.bind(('127.0.0.1', 8086))
new_socket.listen(5)
while True:
conn, addr = new_socket.accept()
recv_choice = conn.recv(1024)
if recv_choice.decode('utf8') == '2':
data = conn.recv(4)
dic_length = struct.unpack('i', data)[0]
dic_json = conn.recv(dic_length)
dic_real = json.loads(dic_json)
file_real_length = dic_real['file_size']
file_real_name = dic_real['filename']
recv_once_length = 0
while recv_once_length < file_real_length:
date_once = conn.recv(1024)
with open(file_real_name, 'wb') as f:
f.write(date_once)
recv_once_length += len(date_once)
else:
conn.send(b'completed')
elif recv_choice.decode('utf8') == '1':
data_base = '/Users/wendywwwww/Desktop/video'
movi- e_name = os.listdir(data_base)
movie_name_dic = {'file_list': movie_name}
movie_name_dic_json = json.dumps(movie_name_dic)
fake_length = struct.pack('i', len(movie_name_dic_json))
conn.send(fake_length)
conn.send(movie_name_dic_json.encode('utf8'))
client_choice = conn.recv(1024)
client_choice = client_choice.decode('utf8')
client_choice = int(client_choice)
file_real_name = movie_name[client_choice - 1]
file_path = os.path.join(data_base, file_real_name)
file_size = os.path.getsize(file_path)
d = {'filename': 'judy的下载', 'file_size': file_size, 'btw': 'enjoy!!!!'}
d_json = json.dumps(d)
d_size = struct.pack('i', len(d_json))
print('1')
conn.send(d_size)
conn.send(d_json.encode('utf8'))
with open(file_path, 'rb') as f:
for line in f:
conn.send(line)
2、客户端
import socket
import struct
import json
import os
new_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
new_socket.connect(('127.0.0.1', 8086))
data_base = '/Users/wendywwwww/Desktop/video'
while True:
choice = input('please choose -> 1 download or 2 upload >>>>>> : ').strip()
if choice == '2':
if choice.isdigit():
new_socket.send(choice.encode('utf8'))
movie_name = os.listdir(data_base)
for i, j in enumerate(movie_name, 1):
print(i, j)
client_choice = input('please choose the number >>>>: ').strip()
if client_choice.isdigit():
client_choice = int(client_choice)
if client_choice in range(1, len(movie_name) + 11):
file_name = movie_name[client_choice - 1]
file_path = os.path.join(data_base, file_name)
file_size = os.path.getsize(file_path)
d = {'filename': 'judy的小测试', 'file_size': file_size, 'btw': 'enjoy!!!!'}
d_json = json.dumps(d)
d_size = struct.pack('i', len(d_json))
new_socket.send(d_size)
new_socket.send(d_json.encode('utf8'))
with open(file_path, 'rb') as f:
for line in f:
new_socket.send(line)
reply=new_socket.recv(1024)
priint(reply.decode('utf8'))
elif choice == '1':
if choice.isdigit():
new_socket.send(choice.encode('utf8'))
data = new_socket.recv(4)
dic_length = struct.unpack('i', data)[0]
dic_json = new_socket.recv(dic_length)
dic_real = json.loads(dic_json)
movie_name_list = dic_real['file_list']
for i, j in enumerate(movie_name_list, 1):
print(i, j)
client_choice = input('please choose the number >>>>: ')
if client_choice.isdigit():
if int(client_choice) in range(1, len(movie_name_list) + 1):
new_socket.send(client_choice.encode('utf8'))
data = new_socket.recv(4)
dic_length = struct.unpack('i', data)[0]
dic_json = new_socket.recv(dic_length)
dic_real = json.loads(dic_json)
file_real_length = dic_real['file_size']
file_real_name = dic_real['filename']
recv_once_length = 0
while recv_once_length < file_real_length:
date_once = new_socket.recv(1024)
with open(file_real_name, 'wb') as f:
f.write(date_once)
recv_once_length += len(date_once)
else:
print('completed')
🌹 测试成功

⚠️ 注意事项
1、变量名后面跟冒号,表示的意思是该变量名需要指代的数据类型
2、函数名+'->'表示后面是函数的返回值
UDP协议
和tcp十分相像
1、服务端
import socket
new_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ip_port = ('127.0.0.1',9090)
new_socket.bind(ip_port)
while True:
msg, address = new_socket.recvfrom(1024)
print(msg, address)
new_socket.sendto(msg.upper(), address)
2、客户端
import socket
new_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ip_port = ('127.0.0.1', 9090)
while True:
data = input('>>>>>: ').strip()
new_socket.sendto(data.encode('utf8'), ip_port)
msg, address = new_socket.recvfrom(1024)
print(msg.decode('utf8'))
socketserver模块的使用
🌹🌹🌹 实现并发
1、服务端
import socketserver
class JUDyrequeat(socketserver.BaseRequestHandler):
def handle(self): # 一定要建立这个函数
while True: #这里干的就是通信循环
data = self.request.recv(1024) # self.request 相当于accept建立的通道
if len(data) == 0:
break
print(data.decode('utf8'))
self.request.send(data.upper())
self.request.close()
server = socketserver.ThreadingTCPServer(('127.0.0.1', 9090), JUDyrequeat, bind_and_activate=True) # ThradingTCPServer 造的是多线程,因为套接字io比较多
server.serve_forever() # server是产生的对象,调出serve_forever表示永远提供服务。干的就是链接循环的工作
2、客户端 # 客户端不变
import socket
new_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = '127.0.0.1'
port = 9090
new_socket.connect((ip, port))
while True:
data = input('>>>>>>: ').strip()
new_socket.send(data.encode('utf8'))
data = new_socket.recv(1024)
print(data.decode('utf8'))
浙公网安备 33010602011771号