python socket serveur

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

bonjour, je travaille sur la réalisation d'un serveur de chat très basique pour le moment en python. Le but de ce serveur est qu'il reçois les données du client et les transmette à tous les autres clients connectés.

Pour cela j'ai utilisé les classes et me suis inspiré de pas mal de tutoriels en anglais sur internet.

Code du 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
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
import socket
import sys
import select

# main variables
_HOST = '127.0.0.1'  # remote host
_PORT = 9979  # remote port
_BUFFER = 4096  # max buffering
_RUNNING = True  # Running variable for the loop while...
_USERS = []


class chat_server():  # chat_server as an object

    def __init__(self):
        self.host = _HOST
        self.port = _PORT
        self.run = _RUNNING
        self.buff = _BUFFER
        self.users = _USERS

    def bind(self): # setting up the server to listen to 5 incoming connections
        """
        Setup and start the server
        """
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.bind((self.host, self.port))
            self.sock.listen(5)
            self.users.append(self.sock)
            sys.stdout.write(('Chat server started : {0} ; {1}').format(self.host, self.port))
        except socket.error:
            sys.stdout.write(('Unable to connect to the remote host : {0}').format(self.host))
            sys.exit()

    def send(self, server, sender, data):
        """
        encode and send the input data to every clients
        """
        for sock in self.users:
            # send the lessage
            if sock != server and sock != sender:
                try:
                    data = data.encode()
                    self.sock.send(data)
                except:
                    # broken socket connection
                    self.sock.close()

                    if sock in self.users:
                        self.users.remove(sock)

    def stop(self):
        self.run = False
        self.sock.close()

    def main(self):
        """
        Principal function of the class chat_server()
        setup and runs the server actually
        """

        self.bind()

        while self.run:

            try:
                ready_to_read, ready_to_write, in_error = select.select(self.users, [], [], 60)
            except socket.error:
                continue

            else:
                for sock in ready_to_read:

                    if sock == self.sock:
                        try:
                            client_socket, client_address = self.sock.accept()
                        except socket.error:
                            break

                        else:
                            self.users.append(client_socket)
                            print('Client (%s, %s) connected' % client_address)

                            # Notifies all connected users that a new one entered the chatroom
                            self.send(self.sock, client_socket, "\n[%s:%s] entered the chatroom\n" % client_address)
                    else:
                        try:
                            data = sock.recv(self.buff)
                            if data:
                                self.send(self.sock, sock, "\r" + '<' + str(sock.getpeername()) + '>' + data)
                        except socket.error:
                            self.send(self.socket, sock, '\nClient (%s, %s) is offline\n' % client_address)
                            print('Client (%s, %s) is offline' % client_address)
                            self.users.remove(sock)
                            continue
        self.stop()





if __name__ == '__main__':
    chat_srv = chat_server()
    chat_srv.main()

et le code du 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
import socket

_HOST = '127.0.0.1'
_PORT = 9979
_BUFFER = 4096
_RUNNING = True

class chat_client():

    def __init__(self):
        self.host = _HOST
        self.port = _PORT
        self.buff = _BUFFER
        self.run = _RUNNING

    def connect(self):
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.connect((self.host, self.port))
        except socket.error:
            print(('Unable to connect to the remote host : {0}').format(self.host))

    def send(self, data):
        _data = data.encode()
        try:
            self.send(_data)
        except socket.error:
            print(('Unable to send the remote message: {0}').format(data))

    def main(self):

        while self.run:

            data = raw_input('<you> ')
            try:
                self.send(data)
            except socket.error:
                print(('Unable to send this message: {0}').format(data))

            data_recv = self.sock.recv(4096)

            if data_recv:

                data = data.decode()
                print(data)



if __name__ == '__main__':
    chat_clt = chat_client()
    chat_clt.main()

voilà, donc je viens vers vous car j'obtient deux erreurs, quand je run le client et qu'il se connecte au serveur, le serveur n'affiche pas le message qui devrait dire qu'un client est arrivé et deuxième c'est que quand j'envoie un message à partir du script du client, le terminal me dit que la limite d'envoi de message à été rejointe et renvoie une erreur en sortie, je pense que c'est à cause de la boucle while True mais n'arrive pas à placer correctement mon self.send…

Voilà, si vous avez des conseils pour améliorer mon code ou vous avez la solution aux problèmes, merci de me donner une réponse. bonne fin de soirée.

+0 -0

Cette réponse a aidé l'auteur du sujet

Je vois quelques erreurs dans le code du client:

  • Tu n'appelles jamais la méthodeconnect. Il faudrait probablement l'appeler au début du main.
  • Dans send, tu appelles send sur self ce qui fait une récursion infinie. Je suppose que c'est plus self.sock.send qu'il faut faire.

Il y a peut-être d'autres erreurs que j'ai raté. Par contre, j'ai l'impression que ton code (surtout le serveur) est particulièrement compliqué par rapport à ce qui devrait être fait en python. Tu n'as pas vraiment plus d'abstraction que du code C, ce qui n'est (il me semble) pas normal en python. La librairie asyncio est, il me semble, plus haut niveau. Ça te permettra de faire ton programme bien plus facilement.

+0 -0
Staff

Cette réponse a aidé l'auteur du sujet

Quel est le but du code, en définitive ?

Je pense que si c'est pour réaliser une petite appli simplement en Python, socketserver fait parfaitement l'affaire. asyncio est également appropriée, mais pour vraiment l'apprécier et ne pas s'y perdre il faut avoir une vague idée de la problématique des IO asynchrones.

Si c'est pour apprendre à faire fonctionner des sockets et l'appel-système select, et écrire un serveur sans tomber dans l'éternel "je reçois une connexion, je lance un thread" (et donc comprendre comment marche asyncio en interne et pourquoi elle est vachement plus élégante que ça), ce code est plutôt un très bon départ.

PS cela dit la classe me semble un peu overkill pour ce code. Vu que le code a déjà un état global, autant utiliser de simples fonctions.

Édité par nohar

I was a llama before it was cool

+1 -0
Auteur du sujet

bonjour, j'ai continué a coder mon serveur de chat mais je trouve un problème, je n'arrive pas à faire interagir le client et le serveur, c'est à dire que ni le client ni le serveur recoivent les données de l'autre et le serveur ne me marque pas que le client est connecté comme il devrait… Je suis perdu.

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
76
77
78
79
80
81
import socket
import sys
import select
import threading

# main variables
_HOST = '127.0.0.1'  # remote host
_PORT = 9959  # remote port
_BUFFER = 1024  # max buffering
_RUNNING = True  # Running variable for the loop while...
_USERS = []

class chat_server():  # chat_server as an object

    def __init__(self):
        self.host = _HOST
        self.port = _PORT
        self.run = _RUNNING
        self.buff = _BUFFER
        self.users = _USERS

    def bind(self): # setting up the server to listen to 5 incoming connections
        """
        Setup and start the server
        """
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.bind((self.host, self.port))
            self.sock.listen(5)
            self.users.append(self.sock)
            print(('Chat server started : {0} ; {1}\n').format(self.host, self.port))
        except socket.error:
            print(('Unable to connect to the remote host : {0}').format(self.host))
            sys.exit()

    def send(self, data): # send back the received data to all connected clients
        for c in self.users:
            try:
                if c != client:
                    c.send(data.encode('utf-8'))
            except:
                pass

    def process(self): # accept and append to the users list the new connection request
        while True:
            try:
                conn, addr = self.sock.accept()
                print(('New connected user : [{0}]').format(conn[0]))
                conn.setblocking(False)
                self.users.append(conn[0])

                data = conn.recv(2048).decode('utf-8')
                print(('from user [{0}]' + data).format(conn[0]))

                if not data:
                    break
            except:
                pass


    def main(self):

        self.bind()

        process = threading.Thread(target = self.process)
        process.daemon = True
        process.start()

        while True:

            cmd = raw_input('[<shell> ]')

            if cmd == 'q':
                self.sock.close()
                sys.exit()
            else:
                self.send(cmd)

if __name__ == '__main__':
    chat_srv = chat_server()
    chat_srv.main()

import socket import sys import threading

_HOST = '127.0.0.1' _PORT = 9959 _BUFFER = 1024 _RUNNING = True

class chat_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
def __init__(self):
    self.host = _HOST
    self.port = _PORT
    self.buff = _BUFFER
    self.run = _RUNNING

def connect(self):
    try:
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((self.host, self.port))
        print('Connected to the host: {0}').format(self.host)
    except socket.error:
        print('Unable to connect to the remote host...')
        sys.exit()

def send(self, data):
    data = (data.encode('utf-8'))
    try:
        self.sock.send(data)
        print('data correctly sended to the server')
    except:
        print("Couldn't send data to the server...")
        sys.exit()

def data_recv(self):
    while True:
        try:
            data_ = (self.sock.recv(1024).decode('utf-8'))
            print(data_)
        except:
            pass


def main(self):

    self.connect()

    recv = threading.Thread(target = self.data_recv)
    recv.daemon = True
    recv.start()

    while self.run:
        data = raw_input('<you> ')

        if data != 'q':
            self.send(data)
        else:
            self.run = False
            sys.exit()

if name == 'main': chat_clt = chat_client() chat_clt.main()

```py si quelqu'un sait résoudre ceci merci de m'en faire part. Bonne soirée

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

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