serveur socket python

a marqué ce sujet comme résolu.

bonjour je viens de trouver un code sur internet qui apriori fonctionnerai pour une communication entre client et serveur en python pour faire un mini chat serveur avec les sockets:

serveur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import socket, select

#Function to broadcast chat messages to all connected clients
def broadcast_data (sock, message):
    #Do not send the message to master socket and the client who has send us the message
    for socket in CONNECTION_LIST:
        if socket != server_socket and socket != sock :
            try :
                socket.send(message.encode())
            except :
                # broken socket connection may be, chat client pressed ctrl+c for example
                socket.close()
                CONNECTION_LIST.remove(socket)

if __name__ == "__main__":

    # List to keep track of socket descriptors
    CONNECTION_LIST = []
    RECV_BUFFER = 4096 # Advisable to keep it as an exponent of 2
    PORT = 5000

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # this has no effect, why ?
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind(("0.0.0.0", PORT))
    server_socket.listen(10)

    # Add server socket to the list of readable connections
    CONNECTION_LIST.append(server_socket)

    print("Chat server started on port " + str(PORT))

    while 1:
        # Get the list sockets which are ready to be read through select
        read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])

        for sock in read_sockets:
            #New connection
            if sock == server_socket:
                # Handle the case in which there is a new connection recieved through server_socket
                sockfd, addr = server_socket.accept()
                CONNECTION_LIST.append(sockfd)
                print("Client (%s, %s) connected" % addr)
                print(CONNECTION_LIST)
                print(type(CONNECTION_LIST))

                broadcast_data(sockfd, "[%s:%s] entered room\n" % addr)

            #Some incoming message from a client
            else:
                # Data recieved from client, process it
                try:
                    #In Windows, sometimes when a TCP program closes abruptly,
                    # a "Connection reset by peer" exception will be thrown
                    data = sock.recv(RECV_BUFFER).decode()
                    if data:
                        broadcast_data(sock, "\r" + '<' + str(sock.getpeername()) + '> ' + data)

                except:
                    broadcast_data(sock, "Client (%s, %s) is offline" % addr)
                    print("Client (%s, %s) is offline" % addr)
                    sock.close()
                    try:
                        CONNECTION_LIST.remove(sock)
                    except:
                        print(CONNECTION_LIST)
                        continue
                    continue

    server_socket.close()

et le client:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import socket, select, string, sys

def prompt() :
    sys.stdout.write('<You> ')
    sys.stdout.flush()

#main function
if __name__ == "__main__":

    if(len(sys.argv) < 3) :
        print('Usage : python telnet.py hostname port')
        sys.exit()

    host = sys.argv[1]
    port = int(sys.argv[2])

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)

    # connect to remote host
    try :
        s.connect((host, port))
    except :
        print('Unable to connect')
        sys.exit()

    print('Connected to remote host. Start sending messages')
    prompt()

    while 1:
        rlist = [sys.stdin, s]

        # Get the list sockets which are readable
        read_list, write_list, error_list = select.select(rlist , [], [])

        for sock in read_list:
            #incoming message from remote server
            if sock == s:
                data = sock.recv(4096).decode()
                if not data :
                    print('\nDisconnected from chat server')
                    sys.exit()
                else :
                    #print data
                    sys.stdout.write(data)
                    prompt()

            #user entered a message
            else :
                msg = sys.stdin.readline()
                s.send(msg.encode())
                prompt()

je l'ai recopié et quelque peu modifié et je l'ai mit sous forme de classe mais mon code marche à moitié , dès que mon client se connecte, il se déconnecte(c'est à dire qu'il reçoit la notification de déconnexion du serveur mais le message de fin de programme ne s'affiche pas, ensuite mon serveur n'accepte qu'un client et je ne sais pas pourquoi… Je vous laisse voir ce que j'ai fait:

serveur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import socket
import sys
import select

# main variables
_HOST = 'localhost'  # host for the server
_PORT = 4567  # remote port
_BUFFER = 1024  # max buffering for data
_RUNNING = True  # main variable to run the principal loop
_USERS = []  # list of all connected users


class Server:  # socket chat server as an object
    def __init__(self):
        self.host = '0.0.0.0'
        self.port = int(_PORT)
        self.buffer = _BUFFER
        self.run = _RUNNING
        self.users = _USERS
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def broadcast_data(self, sock, data):
        for sockt in self.users:
            if socket != self.sock and sockt != sock:
                try:
                    sockt.send(data.encode())
                except:
                    sockt.close()
                    self.users.remove(sockt)

    def main(self):
        try:
            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.sock.bind((self.host, self.port))
            self.sock.listen(10)
            self.users.append(self.sock)
        except socket.error:
            print('Unable to connect ot the remote host: {0}'.format(self.host))

        print('Chat server started on port: ' + str(self.port) + '\n')

        while 1:

            read_sockets, write_sockets, in_error = select.select(self.users, [], [])

            for sockp in read_sockets:
                if sockp == self.sock:
                    # new connection
                    sockfd, addr = self.sock.accept()
                    self.users.append(sockfd)
                    print('Client ({0}) connected\n'.format(addr))
                    self.broadcast_data(sockfd, '[{0}] entered the chatroom\n'.format(addr))

            # some incoming message from the client
            else:
                # data received from the client process it
                try:
                    data = sockp.recv(self.buffer).decode()
                    if data:
                        self.broadcast_data(sockp, '\r' + '<' + str(sockp.getpeername()) + '>' + data)
                except:
                    self.broadcast_data(sockp, 'Client({0}) is offline\n'.format(addr))
                    print('Client({0}) is offline\n'.format(addr))
                    sockp.close()
                    try:
                        self.users.remove(sockp)
                    except:
                        print('\r')
                        continue
                    continue
        self.sock.close()

if __name__ == '__main__':
    server = Server()
    server.main()

et client:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# required modules
import sys
import socket
import select


if (len(sys.argv) < 3):
    print('[usage] python client.py <hostname> <port>')
    sys.exit()

HOST = str(sys.argv[1])
PORT = int(sys.argv[2])


class Client:
    def __init__(self):
        self.host = HOST
        self.port = PORT
        self.run = True
        self.buff = 1024
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.settimeout(2)

    def prompt(self):
        sys.stdout.write('<you> ')
        sys.stdout.flush()

    def main(self):
        try:
            self.sock.connect((self.host, self.port))
        except:
            print('Unable to connect to the remote host: {0}'.format(self.host))
            sys.exit()

        print('connected to the remote host. Start sending messages')
        self.prompt()

        while 1:
            rlist = [sys.stdin, self.sock]

            read_list, write_list, error_list = select.select(rlist, [], [])

            for sock in read_list:

                if sock == self.sock:
                    data = self.sock.recv(self.buff).decode()
                    #if not data:
                     #   print('\nDisconnected from chat server')
                      #  sys.exit()
                    if data:
                        sys.stdout.write(data)
                        self.prompt()
                else:
                    data = sys.stdin.readline()
                    self.sock.send(data.encode())
                    self.prompt()

if __name__ == '__main__':
    client = Client()
    client.main()

je suis totalement perdu… si quelqu'un sait comment faire marcher ce code merci de coeur.

Bonjour,

Pourquoi créer un nouveau sujet et ne pas continuer dans l'un des 3 autres que tu as créés sur le même sujet ?

Sinon, comprends-tu le code que tu as repris ? As-tu pensé à revoir un cours sur les sockets et le mécanisme de select ?

Pourquoi n'utilises-tu pas ta variable _HOST dans le serveur ?

Dans ton code serveur, tu as placé un else au même niveau qu'un for, alors qu'il était associé à un if dans le code initial.

Bonjour,

Pourquoi créer un nouveau sujet et ne pas continuer dans l'un des 3 autres que tu as créés sur le même sujet ?

Sinon, comprends-tu le code que tu as repris ? As-tu pensé à revoir un cours sur les sockets et le mécanisme de select ?

Pourquoi n'utilises-tu pas ta variable _HOST dans le serveur ?

Dans ton code serveur, tu as placé un else au même niveau qu'un for, alors qu'il était associé à un if dans le code initial.

entwanne

merci sa marche parfaitement sauf que je n'arrive pas a faire connecter deux client sur le serveur, une seule connexion passe donc je ne peux pas les faire discuter… Si quelqu'un sait si il faut ajouter quelque chose pour que sa marche merci de m'en faire part au plus vite.

Tes except: sont trop larges. À tous les coups il se passe une erreur non prévue qui ferme les connexions, et le fait que tu ne filtres pas les exceptions que tu rattrapes t'empêche de rendre le problème apparent.

PS : À ta place je ne m'embêterais pas à écrire un client au départ. J'utiliserais directement l'utilitaire netcat pour me connecter au serveur, ça fera toujours deux fois moins de code à débugger.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte