Python socket.error: [Errno 111] В соединении отказано

Пытаюсь написать программу для передачи файлов через сокеты. Серверная часть кода работает нормально. Однако на стороне клиента я получаю следующую ошибку

Traceback (most recent call last):
File "client.py", line 54, in <module>
uploadFiles(directory)
File "client.py", line 36, in uploadFiles
transferFile(fname)
File "client.py", line 13, in transferFile     
cs.connect((HOST, 36258))
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 111] Connection refused

Мой код выглядит следующим образом

import os
import socket

def transferFile(fname):
   HOST = '127.0.0.1'
   CPORT = 36258
   MPORT = 36250
   FILE = fname
   cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   cs.connect((HOST, 36258))
   cs.send("SEND " + FILE)
   cs.close()
   ms = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   ms.connect((HOST, MPORT))
   f = open(FILE, "rb")
   data = f.read()
   f.close()
   ms.send(data)
   ms.close()

def uploadFiles(directory):
   home = os.getenv("HOME")
   folder = str(home + "/" + directory)
   os.chdir(folder)
   dirList = os.listdir(folder)
   print dirList
   for fname in dirList:
       if fname.endswith('.bin'):
           transferFile(fname)

os.chdir(os.getenv("HOME"))
directory = "testdownload"
if not os.path.exists(directory):
   os.makedirs(directory)
 os.chdir(directory)

uploadFiles(directory)

Я пытался искать помощь в Google и других сообщениях на Stack Overflow, ни один из них не помог. Кто-нибудь может мне помочь? Номера строк могут быть разными, так как я вставил только часть кода.


person srnvs    schedule 20.07.2012    source источник
comment
Как узнать, что серверная часть работает? Сообщение об ошибке предполагает, что TCP-соединение с 127.0.0.1:36258 отклонено. Что происходит, когда вы запускаете telnet 127.0.0.1 36258?   -  person tc.    schedule 20.07.2012
comment
Я запустил telnet 127.0.0.1 36258 и смог увидеть соединение. Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Я проверил серверную часть и обнаружил, что возникла проблема с тем, что сокеты не открываются синхронно со стороной клиента. Спасибо   -  person srnvs    schedule 20.07.2012
comment
Чтобы добавить к приведенному выше комментарию, я добавил 2-секундную задержку после cs.close() и после ms.close(), чтобы синхронизировать с соединениями на стороне сервера, и это работало как шарм. Спасибо tc   -  person srnvs    schedule 20.07.2012
comment
Пожалуйста, поясните: как могут cs.close() (на стороне клиента) и ms.close() (на стороне сервера) находиться в одном коде?   -  person Pe Dro    schedule 14.01.2021


Ответы (1)


Проблема, очевидно, заключалась (как вы уже догадались) в том, что порт 36250 не был открыт на стороне сервера в то время, когда вы пытались подключиться (следовательно, в соединении отказано). Я вижу, что сервер должен был открыть этот сокет после получения команды SEND в другом соединении, но он, очевидно, «не открывал [его] синхронно с клиентской стороной».

Ну, основная причина в том, что синхронизации вообще не было. Звонок:

cs.send("SEND " + FILE)
cs.close()

просто поместит данные в буфер ОС; close, вероятно, сбросит данные и отправит их в сеть, но почти наверняка вернется до того, как данные достигнут сервера. Добавление sleep после close может уменьшить проблему, но это не синхронизация.

Правильным решением будет убедиться, что сервер открыл соединение. Для этого потребуется, чтобы сервер отправил вам какое-то сообщение (например, OK, или лучше PORT 36250, чтобы указать, куда подключиться). Это позволит убедиться, что сервер уже слушает.

Другой момент: вы должны проверить возвращаемые значения send, чтобы убедиться, сколько байтов было взято из вашего буфера. Или используйте sendall.

(Извините, что побеспокоил этот поздний ответ, но я обнаружил, что это вопрос с большим объемом трафика, и мне действительно не понравилась идея сна в разделе комментариев.)

person tomasz    schedule 01.12.2014
comment
Могу ли я использовать один и тот же порт на стороне клиента для подключения к нескольким серверам? каждый сервер является копией друг друга. Это просто для балансировки нагрузки запросов. - person y_159; 16.05.2020
comment
@ y_159, насколько мне известно, каждый сервер привязывается к одному порту. Поэтому наличие нескольких серверов в одном порту невозможно. Может ли кто-нибудь проверить мою претензию? - person Adarsh TS; 25.10.2020