webForumDet fria alternativet

Winsock vägrar stänga

C/C++ur C/C++

9 svar · 361 visningar · startad av aleborg

Medlem sedan jan. 20013 341 inlägg
Frågan#1

Jag har ett chat-projekt där jag använder winsock, problemet är att servern inte stänger porten när man kör Close(). Den fortsätter att lyssna och ta emot.
Jag startar servern och den stänger och öppnar som den ska, sen kopplar jag upp en klient mot servern, so far so good...
När jag sen tar close på klienten så körs detta på servern:

			int idx=(p->pUsersList->FindString(0,name));
			p->pUsersList->DeleteString(idx);
			name+= " ***    Leave the chat !";
			p->pMessList->AddString(name);
			POSITION pos=(p->pConnList->Find(this));
			p->pConnList->RemoveAt(pos);
			this->Close();
			p->garbage =this;

men porten fortsätter att lyssna!

Medlem sedan jan. 20013 341 inlägg
#2

kör jag netstat -a så visar den "TIME_WAIT"

Medlem sedan juni 20022 599 inlägg
#3

Att socketen går ner i TIME_WAIT en viss tid (olika länge beroende på operativsystem) efter close har nog att göra med vilka flaggor du använder när du skapar den. Använder du några parametrar som heter nåt i stil med LINGER eller REUSE?

Medlem sedan jan. 20013 341 inlägg
#4

Nej, har kollat i MSDN men hittade inget om det.

Medlem sedan jan. 20013 341 inlägg
#5

Dessa flaggor har jag:
SetSockOpt(TCP_NODELAY,&on,sizeof(BOOL),IPPROTO_TCP);

int on =1;

Medlem sedan juni 20022 599 inlägg
#6

Enligt punkt 3 på den här sidan så ska man kunna tvärdöda en socket genom att anropa setsockopt med SO_LINGER=0 precis innan man anropar close.

Nu misstänker jag att du använder nån sorts MFC-wrappning så det kanske borde bli:

int lingervalue=0;
SetSockOpt(SO_LINGER,&lingervalue,sizeof(int),IPPROTO_TCP);

.. i ditt fall. (OBS: Jag gissar.)

Om man sen tittar under punkt 4 så står det varför man inte bör göra det. De här "zombie"-socketarna är ju bara socketar som ligger kvar en stund (tills operativet tar hand om dem) för att fånga upp eventuella sent inkomna paket och borde inte innebära nåt funktionellt problem. Det är ju sen heller inte så att de verkligen lyssnar (och därmed håller en port), som du skriver.

Medlem sedan jan. 20013 341 inlägg
#7

tack, det smidigaste är väl att sätta en timer på klienten som förhindrar att man kopplar upp sig till samma server inom 1 minut då!

Medlem sedan juni 20022 599 inlägg
#8

OK. Fast jag hänger inte riktigt med i problematiken. En metod när man skriver en chat-server är ju att ha en socket som hela tiden lyssnar och skapar nya sockets i trådar efterhand som klienter ansluter och då uppstår ju inte det här problemet. Är det så att du bara accepterar en anslutning åt gången?

Medlem sedan jan. 20013 341 inlägg
#9

Nej, den tillåter flera, men när samma klient försöker koppla upp direkt så uppstår det här!

Medlem sedan juni 20022 599 inlägg
#10

Skumt. På *nix brukar man tydligen ange SO_REUSEADDR för att slippa detta problem:

/*
* turn off bind address checking, and allow
* port numbers to be reused - otherwise
* the TIME_WAIT phenomenon will prevent
* binding to these address.port combinations
* for (2 * MSL) seconds.
*/

on = 1;

status = setsockopt(serverSocket, SOL_SOCKET, 
  SO_REUSEADDR,
    (const char \*) &on, sizeof(on));

Källa: http://216.239.33.100/search?q=cache:HHuqvfG0uT4J:www.iar.unlp.edu.ar/~fede/revistas/lj/Magazines/LJ46/2333l1.html+setsockopt+SO_LINGER+TIME_WAIT&hl=en&ie=UTF-8

Men på Windows ska det inte behövas vad jag förstår.

134 ms totalt · 3 externa anrop · v20260731065814-full.4bcf49fe
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
131 ms — hämta tråd, inlägg och bilagor (db)