подключите два сокет-клиента, соединенных разными потоками, в качестве пары клиент-сервер через центральный сервер - PullRequest
0 голосов
/ 11 мая 2018

Я хочу отправить файл от одного подключенного клиента другому (оба подключены к центральному серверу и работают в разных потоках), чтобы отправляющий клиент становился сервером, а другой - клиентом. Мой код из основного объекта: lin=link() self.c.send(str('true').encode()) print("sent conf") lin.create_server(new.ip_address,path) функция create_server

def create_server(self,ip,path ):
    connection_list = []
    #ip='127.0.0.1'
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind((ip, 12345))
    print("server created")
    connection_list.append(sock)
    sock.listen(1)
    #offset = 0
    file = open(path, "rb")
    print("file opened")
    while True:
        conn, addr = sock.accept()
        connection_list.append(conn)
        read_sockets,write_sockets,error_sockets = select.select(connection_list,[],[])
        chunk = file.read(4096)
        print("chunk read")
        if not chunk:
            break  # EOF
        sock.send(chunk)
        print("chunk sent")
    print("Transfer complete")
    #sock.shutdown()
    sock.close()

и для создания клиента:

def create_client(self,ip,file ):
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #ip='127.0.0.1'
    print(str(file))
    client.connect((ip, 12346 ))
    print("client created")
    with open(str(file), 'wb') as f:
      socket_list = [client]
      print("file opened")
      while True:
        read_sockets,write_sockets,error_sockets = select.select(socket_list,[],[])
        data=client.recv(4096)
        print("recieved data")
        if not data:
          break
      f.write(data)
      print("Transfer complete")
    f.close()
    time.sleep(5)
    #client.shutdown()
    client.close()

и основная серверная часть, которую я использую для связи с клиентским сокетом, -

for i in self.list_of_conns:#[conn,addr] appended every time a connection is made to main server
                    if i[1][0]==cli_ip:
                        k=i[0]  #the conn from conn,addr=server.accept() part
                        m=1
                        break

и после некоторого кода: k.send(str(addr[0]+' '+filename).encode()) print("sent to k")

Сервер создан, файл для отправки открыт, и главный сервер также отправляет ip на k (последний фрагмент), но соединение, которое должно быть клиентским, не получает его. Куда я иду не так? П.С .: В настоящее время я использую только одну систему и поэтому только один локальный IP для всех сокетов.

1 Ответ

0 голосов
/ 18 мая 2018

Вы испортили свои розетки.

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((ip, 12345))
sock.listen(1)

sock - это сокет, используемый только для прослушивания входящих соединений. Вы не можете читать или писать в этот сокет.

Этот цикл while предназначен для файлов размером более 4096 байт, но каждый раз, когда вы проходите через него, вы ожидаете РАЗНОГО соединения, поэтому первый блок обрабатывается для первого соединения, следующий блок для второго соединения и т. Д.

while True:

    conn, addr = sock.accept()
    chunk = file.read(4096)
    if not chunk:
        break  # EOF

    sock.send(chunk)

Опять же, вы не можете отправить в гнездо для прослушивания! Возможно, вы хотели conn.send(chunk).

То, что вы действительно хотели, было больше похоже на цикл:

conn, addr = sock.accept()
while True:
    chunk = file.read(4096)
    if not chunk:
        break
    conn.send(chunk)
conn.close()

К сожалению, вышеописанное не сработает, поскольку буфер сокетов быстро заполнится и перестанет принимать данные независимо от того, как быстро программа записывает в них данные.

Вам необходимо проверить возвращаемое значение из conn.send(chunk), чтобы узнать, сколько байтов было отправлено. Если это меньше, чем длина chunk, вам нужно удалить столько байтов из начала чанка и попытаться отправить остаток. Повторяйте, пока весь кусок не будет отправлен.

Или ... просто используйте conn.sendall(chunk), который блокирует, пока все данные не будут приняты в буфер сокетов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...