Bonjour,

J'ai réalisé des sockets php (client et serveur) mais je me heurte à un problème, lorsque dans mon onglet 1 j'attends des données, je ne peux pas écrire avec une nouvelle socket grâce à l'onglet 2.

Je ne sais pas si l'option non block peut résoudre mon problème, je n'ai pas bien compris comment m'en servir.

Par ailleurs, lorsque j'écoute mon serveur, dès que j'ai la réponse, je ferme ma connexion, ce n'est pas comme ceci que Stephane Eyskens fait, il affiche l'ip:port dans une frame, recupère le contenu d'avant et ajout le nouveau message.

Serveur :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/local/php53/bin/php-cgi -q
<?php
 
set_time_limit (0);
ob_implicit_flush();
require_once 'includes/application_top.php';
error_reporting(E_ALL);
// SOCKET_SERVER localhost
// SOCKET_PORT_ORDER 8081
$socket = new Socket(SOCKET_SERVER, SOCKET_PORT_ORDER); // include/configure.php && administration/include/configure.php
$socket->start();
$socket->listen();

Client (lecture) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
$socket = new Socket(SOCKET_SERVER, $_REQUEST['port']);
$socket->read();
Client (écriture) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
$socket = new Socket('localhost', '8081');
var_dump($socket->write('Bonjour : ' . date('H:i:s')));
La console serveur :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
Nouveau client connecté : Resource id #66
Total des clients : 1
Message reçu de Resource id #67 : Bonjour : 12:48:07
Diffusion du message Bonjour : 12:48:07
Ressource Resource id #66...OK
Fermeture de la socket Resource id #67
Voici la classe que j'utilise :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
class Socket {
 
    private $adress;
    private $port;
    private $socket;
    private $clients = array();
    private $buffer  = 128;
    private $new     = 'yo';
 
    public function __construct($adress, $port) {
        $this->adress = $adress;
        $this->port   = $port;
        $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    }
 
    /**
     * Démarre la socket et l'écoute
     * @return  Mixed   String erreur | rien
     */
    public function start()
    {
        echo PHP_EOL;
        echo '==============================';
        echo PHP_EOL;
        echo 'Création de la socket...';
        if ($this->socket === false) {
            echo PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'socket_create() a échoué raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
            exit;
        } else {
            echo 'OK' . PHP_EOL;
        }
 
        echo 'Connexion à la socket ' . $this->adress . ':' . $this->port . '...';
        if (!socket_bind($this->socket, $this->adress, $this->port)) {
            echo PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'socket_bind() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
            socket_close($this->socket);
            exit;
        } else {
            echo 'OK' . PHP_EOL;
        }
 
        echo 'Ecoute de la socket...';
        if (!socket_listen($this->socket)) { // Start listening for connections
            echo PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'socket_listen() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
            socket_close($this->socket);
            exit;
        } else {
            echo 'OK' . PHP_EOL;
        }
        echo '==============================' . PHP_EOL;
    }
 
    /**
     * A démarrer sur le serveur #!/usr/local/php53/bin/php-cgi -q
     * Ecoute l socket
     * @return type
     */
    public function listen()
    {
        echo 'Prêt à écouter les clients';
 
        if ($this->socket === false) {
            echo PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'listen() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
            $this->closeSocket();
            exit;
        }
 
        echo '...OK' . PHP_EOL;
        echo 'Nombre de client : ' . count($this->clients) . PHP_EOL;
        echo '==============================' . PHP_EOL;
 
        while (true) : // Loop continuously
 
            if (!($ressource = socket_accept($this->socket))) { // plus de socket
                $error = socket_last_error($this->socket);
                if ($error != 11 && $error != 115) {
                    echo PHP_EOL . PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'socket_accept() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror($this->socket) . PHP_EOL;
                }
                //exit;
            } else {
                $this->readAndWrite($ressource);
            }
 
        endwhile;
    }
 
    /**
     * Récupère les nouvelles sockets
     * @param Socket $ressource
     */
    private function readAndWrite($ressource)
    {
        if (!is_resource($ressource)) {
            echo PHP_EOL . PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'is_resource() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
            //exit;
        }
 
 
        // si ecriture on transmet
        // sinon ecoute, on le stock avec les autres.
 
        $buffer = socket_read($ressource, $this->buffer);
 
        if (!empty($buffer) && $buffer === 'kill') {
            $this->clients[] = $ressource;
            echo 'Kill...' . PHP_EOL;
            $this->closeSocket();
        } elseif (!empty($buffer) && $buffer != $this->new) {
            echo 'Message reçu de ' . $ressource . ' : ' . $buffer . PHP_EOL;
            $this->writeToClient($buffer);
            echo 'Fermeture de la socket ' . $ressource . PHP_EOL;
        } elseif (!in_array($ressource, $this->clients)) { // Nouveau client
            $this->clients[] = $ressource;
            echo 'Nouveau client connecté : ' . $ressource . PHP_EOL;
            echo 'Total des clients : ' . count($this->clients) . PHP_EOL;
        }
    }
 
    /**
     * Notification de à tous les clients connectés
     * @param String $msg
     */
    private function writeToClient($msg)
    {
        echo 'Diffusion du message ' . $msg . PHP_EOL;
 
        foreach ($this->clients as $key => $socket) :
            if (!is_resource($socket)) {
                unset($this->clients[$key]);
            } else {
 
                echo 'Ressource ' . $socket . '...';
 
                if (!@socket_write($socket, $msg, strlen($msg))) {
                    //echo PHP_EOL . PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'socket_write() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
                    unset($this->clients[$key]);
                    echo 'ECHEC : ressource fermée' . PHP_EOL;
                } else {
                    echo 'OK' . PHP_EOL;
                }
 
            }
        endforeach;
    }
 
    /**
     * Déconnecte tous les clients
     */
    private function disconnectAllClient()
    {
        echo 'Nombre de client : ' . count($this->clients) . PHP_EOL;
        $this->writeToClient('Le serveur va être arrêté.');
 
        foreach ($this->clients as $key => $socket) :
            if (!is_resource($socket)) {
                echo 'Déconnexion du client : ' . $socket . PHP_EOL;
                @socket_close($socket);
            }
        endforeach;
    }
 
    /**
     * Ferme la socket mère
     */
    private function closeSocket()
    {
        $this->disconnectAllClient();
 
        if ($this->socket !== null) {
            echo 'Fermeture de la session...';
            socket_shutdown($this->socket, 1);//remote host yet can read
            usleep(500);//wait remote host
            socket_shutdown($this->socket, 0);//close reading
            socket_close($this->socket);//finaly we can free resource
            echo 'OK' . PHP_EOL;
        }
 
        exit(PHP_EOL . 'Socket fermée.' . PHP_EOL);
    }
 
    /**
     * Client
     */
 
    public function read()
    {
        if (!@socket_connect($this->socket, $this->adress, $this->port)) {
            echo PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'socket_connect() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
            return null;
        }
 
        socket_write($this->socket, $this->new, strlen($this->new));
 
        $i = 0;
 
        while ($i < 10) :
            echo socket_read($this->socket, $this->buffer);
            sleep(1);
            $i++;
        endwhile;
 
        echo '<hr>';
 
        socket_close($this->socket);
    }
 
    public function write($msg)
    {
        if (!@socket_connect($this->socket, $this->adress, $this->port)) {
            //echo PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'socket_connect() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
            return null;
        }
 
        if (!@socket_write($this->socket, $msg, strlen($msg))) {
            //echo PHP_EOL . __FILE__ . ':' . __LINE__ . PHP_EOL . PHP_EOL . 'socket_write() a échoué adresse : ' . $this->adress . ':' . $this->port . ' raison : ' . socket_strerror(socket_last_error()) . PHP_EOL;
        }
 
        socket_close($this->socket);
 
        return true;
    }
}