Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

socket : je comprend plus rien !!!

4 réponses
Avatar
Sylvain Bénot
Bonjour,

En faisant des tests avec une application "client/serveur" minimale je
viens de m'apercevoir que la fonction connect() ne renvoie pas d'erreur
du moment que l'application "serveur" a fait un listen() et qu'il reste
de la place dans la file d'attente des connexions. C'est normal ?
Je croyais que le connect() restait bloqué jusqu'a ce que le "serveur"
fasse un accept() (avec des sockets bloquantes bien entendu).
Merci de m'éclairer car la je comprend plus rien.

Ci-dessous le code minimal des applis avec lesquelles j'ai fait les tests.

Sylvain


SERVEUR
-------

#include "stdafx.h"
#include "winsock2.h"


void main(int argc, char* argv[])
{
//----------------------
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");

//----------------------
// Create a SOCKET for listening for
// incoming connection requests.
SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return;
}

//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("10.4.20.108");
service.sin_port = htons(27015);

if (bind( ListenSocket,
(SOCKADDR*) &service,
sizeof(service)) == SOCKET_ERROR) {
printf("bind() failed.\n");
closesocket(ListenSocket);
return;
}

//----------------------
// Listen for incoming connection requests.
// on the created socket
if (listen( ListenSocket, 1 ) == SOCKET_ERROR)
printf("Error listening on socket.\n");

while(1)
{
printf( "." );
Sleep( 1000 );
}

WSACleanup();
return;
}

CLIENT
-------

#include "stdafx.h"
#include "winsock2.h"


int main(int argc, char* argv[])
{
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()\n");

//----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return 0;
}

//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "10.4.20.108" );
clientService.sin_port = htons( 27015 );

//----------------------
// Connect to server.
int res;
res = connect( ConnectSocket, (SOCKADDR*) &clientService,
sizeof(clientService) );
if ( res == SOCKET_ERROR)
{
printf( "Failed to connect (%d).\n", WSAGetLastError() );
WSACleanup();
return 0;
}

printf("Connected to server. (%d)\n", ConnectSocket );
Sleep( 20000 );
WSACleanup();
return 0;
}

4 réponses

Avatar
Cyrille Szymanski
On 2005-04-04, Sylvain Bénot wrote:
Bonjour,

En faisant des tests avec une application "client/serveur" minimale je
viens de m'apercevoir que la fonction connect() ne renvoie pas d'erreur
du moment que l'application "serveur" a fait un listen() et qu'il reste
de la place dans la file d'attente des connexions. C'est normal ?
Je croyais que le connect() restait bloqué jusqu'a ce que le "serveur"
fasse un accept() (avec des sockets bloquantes bien entendu).
Merci de m'éclairer car la je comprend plus rien.



Au temps pour moi, connect() retourne dès que la socket distante est contactée
et non lorsque la connexion est acceptée.

Ci-dessous le code minimal des applis avec lesquelles j'ai fait les tests.



Ok, c'est apparemment en partie du code de MSDN, mais malheureusement même
celui-ci n'est pas à 100% correct.

J'avoue que ça relève du détail.


SERVEUR
-------

#include "stdafx.h"
#include "winsock2.h"


void main(int argc, char* argv[])
{
//----------------------
// Initialize Winsock.
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()n");



Logiquement il faudrait faire un return ici.

//----------------------
// Create a SOCKET for listening for
// incoming connection requests.
SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);



PF=protocol family
AF­dress family

Là en toute rigueur c'est PF_INET et pas AF_INET mais coup de chance les deux
sont définis à la même valeur. Tout le monde fait "l'erreur".

if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ldn", WSAGetLastError());
WSACleanup();
return;
}

//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service;
service.sin_family = AF_INET;



Ici le AF_INET est correct par contre.

service.sin_addr.s_addr = inet_addr("10.4.20.108");
service.sin_port = htons(27015);



Il faudrait aussi initialiser service.sin_size.

if (bind( ListenSocket,
(SOCKADDR*) &service,
sizeof(service)) == SOCKET_ERROR) {
printf("bind() failed.n");
closesocket(ListenSocket);



Et il manque un WSACleanup()

return;
}

//----------------------
// Listen for incoming connection requests.
// on the created socket
if (listen( ListenSocket, 1 ) == SOCKET_ERROR)
printf("Error listening on socket.n");

while(1)
{
printf( "." );
Sleep( 1000 );
}



Voir la faq winsock pour fermer correctement la socket.

WSACleanup();
return;
}

CLIENT
-------

#include "stdafx.h"
#include "winsock2.h"


int main(int argc, char* argv[])
{
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
printf("Error at WSAStartup()n");



idem

//----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);



idem

if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ldn", WSAGetLastError());
WSACleanup();
return 0;
}

//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "10.4.20.108" );
clientService.sin_port = htons( 27015 );



idem


//----------------------
// Connect to server.
int res;
res = connect( ConnectSocket, (SOCKADDR*) &clientService,
sizeof(clientService) );
if ( res == SOCKET_ERROR)
{
printf( "Failed to connect (%d).n", WSAGetLastError() );



closesocket() manquant

WSACleanup();
return 0;
}

printf("Connected to server. (%d)n", ConnectSocket );
Sleep( 20000 );



Voir la faq pour fermer correctement la socket.

WSACleanup();
return 0;
}




A+
--
Cyrille Szymanski
Avatar
Sylvain Bénot
Cyrille Szymanski a écrit:
On 2005-04-04, Sylvain Bénot wrote:

Bonjour,

En faisant des tests avec une application "client/serveur" minimale je
viens de m'apercevoir que la fonction connect() ne renvoie pas d'erreur
du moment que l'application "serveur" a fait un listen() et qu'il reste
de la place dans la file d'attente des connexions. C'est normal ?
Je croyais que le connect() restait bloqué jusqu'a ce que le "serveur"
fasse un accept() (avec des sockets bloquantes bien entendu).
Merci de m'éclairer car la je comprend plus rien.




Au temps pour moi, connect() retourne dès que la socket distante est contactée
et non lorsque la connexion est acceptée.





Est-ce que c'est moi qui ait mal lu la doc de la fonction connect() ou
c'est pas expliquer ?
Il y a quand même la phrase "When the socket call completes
successfully, the socket is ready to send/receive data." qui pour moi
veut dire qu'on est connecté et qu'on peut communiquer sur la socket.
Avatar
Cyrille Szymanski
On 2005-04-07, Sylvain Bénot wrote:

Au temps pour moi, connect() retourne dès que la socket distante est contactée
et non lorsque la connexion est acceptée.



Est-ce que c'est moi qui ait mal lu la doc de la fonction connect() ou
c'est pas expliquer ?



En fait il n'y a jamais écrit que connect() retourne une fois que l'hôte
distant a appelé accept().

Il y a quand même la phrase "When the socket call completes
successfully, the socket is ready to send/receive data." qui pour moi
veut dire qu'on est connecté et qu'on peut communiquer sur la socket.



Oh que cette phrase est trompeuse !

Il ne faut pas oublier que Winsock n'a pas été écrit spécifiquement pour TCP/IP
mais que cette API est utilisée avec beaucoup d'autres protocoles très
différents. En clair, Winsock ça ressemble à du TCP/IP mais c'est pas calqué à
100% dessus ; on ne peut pas calquer chaque appel de fonction sur un mécanisme
du protocole.

Un appel à accept() ne déclenche aucune action au niveau du protocole (pas
d'envoi/réception de packets) mais enlève et retourne la première connexion non
encore acceptée de la file d'attente. Dans cette file, il n'y a que des
connexions établies (du point de vue du protocole).

Un appel à connect() retourne dès que la connexion est établie avec l'hôte
distant, c'est à dire dès que la connexion est ajoutée à sa file d'attente.

A+
--
Cyrille Szymanski
Avatar
Sylvain Bénot
Merci pour toutes ces précisions.

Sylvain




Cyrille Szymanski a écrit:
On 2005-04-07, Sylvain Bénot wrote:

Au temps pour moi, connect() retourne dès que la socket distante est contactée
et non lorsque la connexion est acceptée.



Est-ce que c'est moi qui ait mal lu la doc de la fonction connect() ou
c'est pas expliquer ?




En fait il n'y a jamais écrit que connect() retourne une fois que l'hôte
distant a appelé accept().


Il y a quand même la phrase "When the socket call completes
successfully, the socket is ready to send/receive data." qui pour moi
veut dire qu'on est connecté et qu'on peut communiquer sur la socket.




Oh que cette phrase est trompeuse !

Il ne faut pas oublier que Winsock n'a pas été écrit spécifiquement pour TCP/IP
mais que cette API est utilisée avec beaucoup d'autres protocoles très
différents. En clair, Winsock ça ressemble à du TCP/IP mais c'est pas calqué à
100% dessus ; on ne peut pas calquer chaque appel de fonction sur un mécanisme
du protocole.

Un appel à accept() ne déclenche aucune action au niveau du protocole (pas
d'envoi/réception de packets) mais enlève et retourne la première connexion non
encore acceptée de la file d'attente. Dans cette file, il n'y a que des
connexions établies (du point de vue du protocole).

Un appel à connect() retourne dès que la connexion est établie avec l'hôte
distant, c'est à dire dès que la connexion est ajoutée à sa file d'attente.

A+