Как мне разорвать соединение, если клиент отключается от сервера? - PullRequest
0 голосов
/ 29 декабря 2018

Я написал сервер и клиент, и если я закрою свой клиент и снова подключусь, мой список клиентов на сервере просто складывается.В первый раз, когда я отключаюсь, я распечатываю то, что в списке, поэтому сначала я получаю это:

{612: <socket.socket fd=612, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.77', 22050), raddr=('192.168.1.77', 53531)>

Во второй раз, когда я подключаюсь, он просто складывается так, что выглядит так:

{612: <socket.socket fd=612, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.77', 22050), raddr=('192.168.1.77', 53531)>, 620: <socket.socket fd=620, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.77', 22050), raddr=('192.168.1.77', 53532)>}

Каксделать так, чтобы он просто сбрасывал соединение? Вот код сервера:

import socket
import threading
from _thread import *
from threading import Thread

clients = {}

def message(c):
    while True:
        try:
            data = c.recv(1024).decode("utf-8")
            print("Recieved from: " + str(data))
            if not data:
                print("Client Disconnected.")
                print(clients)
                break

            # skicka meddelanden till client
            for client in clients.values():
                try:
                    if client == c:
                        continue
                    client.sendall(data.encode("utf-8"))
                except ConnectionAbortedError:
                    print("[!] Connection aborted ")
                    print(str(clients))
                except ConnectionResetError:
                    print("[!] Connection reset error ")
                    print(str(clients))
        except ConnectionResetError:
            print("[!] - An existing connection was forcibly closed by the remote host. \n")
            break

def listener():
    host = "192.168.1.77"
    port = 22050
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((host, port))
    s.listen(5)
    print("\nServer has started.\n\n" + "Host: " + host + "\nPort: " + str(port))
    print("______________________________________________________________________\n")
    while True:
        c, addr = s.accept()
        print(str(addr) + " has connected.")
        clients[c.fileno()] = c
        threading.Thread(target=message, args=(c,)).start()


if __name__ == '__main__':
    listenerthread = Thread(target=listener())
    listenerthread.start
    #listener()

А вот код клиента:

import socket
import os
from multiprocessing import Process
from threading import Thread
import sys

print("... Awaiting connection from server ...")

host = "192.168.1.77"
port = 22050

try:
    s = socket.socket()
    s.connect((host, port))
except ConnectionRefusedError:
    print("Server is down.")
    sys.exit()
try:
    print("Connected!")

    def send():
        while True:
           message = input("-> ")
           s.send(message.encode("utf-8"))
           #recieve = s.recv(1024).decode("utf-8")
           #print("- Server: " + recieve)

    def recv():
        recieve = s.recv(1024).decode("utf-8")
        print("\n" + "Server: " + recieve)

#    while message !="quitclient":
#        s.send(message.encode("utf-8"))
#        recieve = s.recv(1024).decode("utf-8")
#        print("Recieved from server: " + recieve)
#        message = input("-> ")
#    s.close()

except ConnectionResetError:
    print("Disconnected!")
    input("Press enter to exit...")
    quit()
sendthread = Thread(target=send)
recvthread = Thread(target=recv)

sendthread.start()
recvthread.start()

Код клиента простоУ меня есть версия клиентского кода GUI (не пишу так долго), но тот же код.В версии с графическим интерфейсом у меня есть кнопка отключения, которая выглядит следующим образом:

def Disconnect():
    s.shutdown(socket.SHUT_RDWR)
    s.close()

Что я здесь не так делаю?

1 Ответ

0 голосов
/ 29 декабря 2018

Словарь clients добавляется, но не удаляется.Что-то вроде следующего должно работать.Перехватите любое исключение и пропустите, чтобы удалить ключ из словаря.

def message(c):
    try:
        while True:
            data = c.recv(1024).decode("utf-8")
            print("Received from: " + str(data))
            if not data:
                print("Client Disconnected.")
                print(clients)
                break

            # skicka meddelanden till client
            for client in clients.values():
                if client == c:
                    continue
                client.sendall(data.encode("utf-8"))
    except Exception as e:
        print(e)
    clients.pop(c.fileno())
    print(clients)

Кроме того, приведенный ниже код никогда не запускает поток из-за необходимости start(), а не start.Слушатель запускается, потому что он вызывается в target=listener(), который должен быть target=listener:

if __name__ == '__main__':
    listenerthread = Thread(target=listener())
    listenerthread.start
    #listener()

Но запуск потока для вызова слушателя не требуется.Просто используйте:

if __name__ == '__main__':
    listener()

У вас также могут возникнуть проблемы с сообщениями.TCP является потоковым протоколом, поэтому вы не можете предполагать, что каждый recv получает именно то, что отправил send.send не гарантирует, что он будет отправлять каждый байт либо ... проверьте возвращаемое значение, либо используйте sendall.Небольшие сообщения, отправляемые медленно, могут никогда не показывать проблему, но отправляйте большие сообщения, полные многобайтовых символов в кодировке UTF-8, и вы получите ошибку.См. мой недавний ответ , чтобы узнать, как его решить.

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