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

Libération de port - winsock

4 réponses
Avatar
Julien Ghaye
Bonjour tous le monde,

Je suis actuellement en train de coder une appli client qui interagit
avec le port 80 d'un serveur (un client http).

Seulement, j'ai remarqué qu'après la création de plusieurs socket (plus
de 3900) assez rapidement, j'obtient systématiquement l'erreur 10048
(address in use). D'après ce que j'ai pu constater, c'est le port local
qui n'est pas libéré lorsque je fais un closesocket().

Ma question est donc : Comment fait on pour libérer le port? Comment
dire au système qu'on ne l'utilise plus.

Voici un bout de code (codé en vitesse) qui met en évidence l'erreur. Il
se connect et se déconnect immédiatement du port 80 d'un serveur (en
l'occurence 127.0.0.1)

Merci à tous ;-)
Julien


///////////////////// CODE ////////////////////


#include <iostream>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")

using namespace std;

int host(SOCKET s, char* buff, int* length)
{
sockaddr name;
int namelen = sizeof(sockaddr);
if ((getsockname(s,&name,&namelen) == SOCKET_ERROR) ||
(WSAAddressToString(&name,namelen,NULL,buff,(LPDWORD)length) ==
SOCKET_ERROR))
{
cout << "An error Occurs .... error code : " << WSAGetLastError() <<
endl;
return -1;
}
return 0;
}


void main()
{
WSADATA WSAData;
SOCKET sock = INVALID_SOCKET;
SOCKADDR_IN sin;
int buff_len = 255;
char *buffer = new char[buff_len];

cout << "Stratup" << endl;
WSAStartup(MAKEWORD(2,0), &WSAData);
bool optVal = true;

while(true)
{
sock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_family = AF_INET;
sin.sin_port = htons(80);
cout << "Connecting " ;
if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR)
{
cout << " ... Error : " << WSAGetLastError() << endl;
break;
}
//setsockopt(sock,SOL_SOCKET,SO_EXCLUSIVEADDRUSE,(char *)&optVal,
sizeof(bool));
host (sock, buffer, &buff_len);
cout << "from" << buffer << "\r";
closesocket(sock);
sock = INVALID_SOCKET;
}
cout << "Cleaning up" << endl;
sock = INVALID_SOCKET;
WSACleanup();
cin >> new char;
}

4 réponses

Avatar
Michael DOUBEZ
Bonjour tous le monde,

Je suis actuellement en train de coder une appli client qui interagit
avec le port 80 d'un serveur (un client http).

Seulement, j'ai remarqué qu'après la création de plusieurs socket (plus
de 3900) assez rapidement, j'obtient systématiquement l'erreur 10048
(address in use). D'après ce que j'ai pu constater, c'est le port local
qui n'est pas libéré lorsque je fais un closesocket().


C'est dû au protocole TCP et au système de terminaison 3 hand shake. Le
système continue d'écouter sur le port local pour envoyer un RESET si un
paquet arrive.

Je ne connait pas windows mais je ne pense pas que ce soit la raison de
l'erreur (il y a plus de 3900 ports locaux libres). Ca ressemble à une
limitation à 4092 qq chose.


Ma question est donc : Comment fait on pour libérer le port? Comment
dire au système qu'on ne l'utilise plus.

Voici un bout de code (codé en vitesse) qui met en évidence l'erreur. Il
se connect et se déconnect immédiatement du port 80 d'un serveur (en
l'occurence 127.0.0.1)[snip]


Peut être un groupe windows t'aideras plus. Ou en cherchant un code de
crawler sur le net.

Michael

Avatar
Laurent Pointal
Bonjour tous le monde,

Je suis actuellement en train de coder une appli client qui interagit
avec le port 80 d'un serveur (un client http).

Seulement, j'ai remarqué qu'après la création de plusieurs socket (plus
de 3900) assez rapidement, j'obtient systématiquement l'erreur 10048
(address in use). D'après ce que j'ai pu constater, c'est le port local
qui n'est pas libéré lorsque je fais un closesocket().


Peut être une piste: setsockopt avec SO_REUSEADDR

http://www.google.fr/search?hl=fr&q=SO_REUSEADDR

=> http://blogs.msdn.com/wndp/archive/2005/08/03/Anthony-Jones.aspx

Pas sécure... mais peut aider à réutiliser les ports.

Ma question est donc : Comment fait on pour libérer le port? Comment
dire au système qu'on ne l'utilise plus.

Voici un bout de code (codé en vitesse) qui met en évidence l'erreur. Il
se connect et se déconnect immédiatement du port 80 d'un serveur (en
l'occurence 127.0.0.1)

Merci à tous ;-)
Julien


A+

Laurent.

Avatar
James Kanze
On Aug 9, 12:07 pm, Michael DOUBEZ wrote:
Je suis actuellement en train de coder une appli client qui interagit
avec le port 80 d'un serveur (un client http).

Seulement, j'ai remarqué qu'après la création de plusieurs socket (plus
de 3900) assez rapidement, j'obtient systématiquement l'erreur 10048
(address in use). D'après ce que j'ai pu constater, c'est le port loc al
qui n'est pas libéré lorsque je fais un closesocket().


C'est dû au protocole TCP et au système de terminaison 3 hand shake. Le
système continue d'écouter sur le port local pour envoyer un RESET si un
paquet arrive.


La question n'a réelement rien à voir avec le C++, mais il est
possible (probable ?) aussi que le système ne réutilise pas le
numéro de port tout de suite. Même si on l'a fermé de son côté,
c'est possible qu'il y a des trames qui lui sont destinées et
qui trainent quelque part dans la toile. Ça ne m'étonnerait donc
pas que le numéro de port reste reservé quelque sécondes après
la fermature complète (c-à-d la fin du hand shack).

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
espie
In article ,
James Kanze wrote:
La question n'a réelement rien à voir avec le C++, mais il est
possible (probable ?) aussi que le système ne réutilise pas le
numéro de port tout de suite. Même si on l'a fermé de son côté,
c'est possible qu'il y a des trames qui lui sont destinées et
qui trainent quelque part dans la toile. Ça ne m'étonnerait donc
pas que le numéro de port reste reservé quelque sécondes après
la fermature complète (c-à-d la fin du hand shack).


30 secondes a 2 minutes selon les systemes. Ca fait partie du protocole.
Ca permet d'eviter de s'emmeler les pinceaux entre deux connexions.
Le temps en question a ete calcule a la louche par rapport au TTL des
paquets. La connexion est en fait asymetrique: seul le bout qui ferme
la connexion est oblige d'avoir ce delai supplementaire. C'est une des
conneries du protocole HTTP, et c'est pour ca que, dans les protocoles
bien concus, c'est le *client* qui ferme la connexion. (une fin normale
de connexion, c'est un FIN / FIN,Ack / Ack. Le Ack final peut se perdre,
auquel cas l'autre bout renverra un FIN,Ack apres la fin du timeout,
et il n'y a pas de facon de savoir que le paquet s'est perdu sans constater
une reemission.

Note qu'on peut ruser, ce que font des systemes intelligents: la
restriction sur la reutilisation d'un port peut etre leve si la connexion
provient d'une autre adresse IP, et si on sait retrouver ou arrive chaque
paquet.

Les fonctionnalites a la SO_REUSEADDR sont *exclusivement* concues pour
des situations de tests (style, montee en charge rapide sur un reseau
local...)