Newsgroup: it.comp.lang.c
Titolo: Perche` la connect non si blocca?

Ciao a tutti.
Qualcuno sa dirmi come mai su win32 (per ora ho provato solo li`) la 
connect contenuta nella seguente funzione non si blocca?
int my_socketpair(SOCKET socks[2])
{
    SOCKET				listener	=
	INVALID_SOCKET;
    int					addrlen		=
	sizeof(struct sockaddr_in);
    struct sockaddr_in	addr;
    memset(&addr, 0, sizeof(addr));
    if(socks){
		socks[0]	=	socks[1]	=	INVALID_SOCKET;
		if((listener=socket(AF_INET, SOCK_STREAM, 0))!
=INVALID_SOCKET){
			addr.sin_family			=
	AF_INET;
			addr.sin_addr.s_addr	=	htonl
(INADDR_LOOPBACK);
			addr.sin_port			=
	0;
			if(bind(listener, (const struct sockaddr*)
&addr, sizeof(struct sockaddr_in))!=SOCKET_ERROR){
				if(getsockname(listener, (struct 
sockaddr*)&addr, &addrlen)!=SOCKET_ERROR){
					if(listen(listener, 1)!
=SOCKET_ERROR){
						if((socks[0]
=socket(AF_INET, SOCK_STREAM, 0))!=INVALID_SOCKET){
							if
(connect(socks[0], (const struct sockaddr*)&addr, sizeof(addr))!
=SOCKET_ERROR){
/*
*							
	int ret	=	send(socks[0], "prova", strlen("prova"), 0);
*/
 
	if((socks[1]=accept(listener, NULL, NULL))!=INVALID_SOCKET){
/*
*							
		char	prova[sizeof("prova")]	=	{'\0'};
*							
		int ret	=	recv(socks[1], prova, sizeof
(prova), 0);
*/
 
		closesocket(listener);
 
		return	0;
 
	}
							}
						}
					}
				}
			}
			if(listener!=INVALID_SOCKET){
				closesocket(listener);
				listener	=	INVALID_SOCKET;
			}
			if(socks[0]!=INVALID_SOCKET){
				closesocket(socks[0]);
				socks[0]	=	INVALID_SOCKET;
			}
			if(socks[1]!=INVALID_SOCKET){
				closesocket(socks[1]);
				socks[1]	=	INVALID_SOCKET;
			}
		}
    }else{
		WSASetLastError(WSAEINVAL);    	
    }
	return	SOCKET_ERROR;
}
Da notare che se setto l'opzione FIONBIO per rendere il socket non 
bloccante, allora magicamente mi prendo un EWOULDBLOCK alla connect.
Da notare anche che se effettuo una send prima della accept, essa 
funziona senza problemi e il dato viene correttamente ricevuto subito 
dopo la accept.
Mi verrebbe da pensare che la causa scatenante sia l'indirizzo di 
loopback o forse la porta effimera che viene allocata sul listener...ma 
non ho trovato nessun conforto nella specifica della connect.
Qualcuno di voi si e` mai imbattuto in dilemma simile?
Grazie a tutti (spero che il layout del cut&paste sia leggibile).
-- Ale

Il layout faceva schifissimo, chiedo scusa e ci riprovo, cosi` mi sembra 
un pochino meglio:
int my_socketpair(SOCKET socks[2])
{
 SOCKET listener = INVALID_SOCKET;
 int    addrlen  = sizeof(struct sockaddr_in);
 struct sockaddr_in addr;
 memset(&addr, 0, sizeof(addr));
 if(socks){
  socks[0] = socks[1] = INVALID_SOCKET;
  if((listener=socket(AF_INET, SOCK_STREAM, 0))!=INVALID_SOCKET){
   addr.sin_family      = AF_INET;
   addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
   addr.sin_port        = 0;
   if(bind(listener, (const struct sockaddr*)&addr, sizeof(struct 
sockaddr_in))!=SOCKET_ERROR){
    if(getsockname(listener, (struct sockaddr*)&addr, &addrlen)!
=SOCKET_ERROR){
     if(listen(listener, 1)!=SOCKET_ERROR){
      if((socks[0]=socket(AF_INET, SOCK_STREAM, 0))!=INVALID_SOCKET){
       if(connect(socks[0], (const struct sockaddr*)&addr, sizeof(addr))!
=SOCKET_ERROR){
/*
*        int ret = send(socks[0], "prova", strlen("prova"), 0);
*/
        if((socks[1]=accept(listener, NULL, NULL))!=INVALID_SOCKET){
/*
*         char prova[sizeof("prova")] = {'\0'};
*         int ret = recv(socks[1], prova, sizeof(prova), 0);


 
Grazie a chi ha esperienza di winsock e puï¿œ dire se ci ho imbroccato o 
ti sto fuorviando ;D
lb

 nuova connessione: viene rifiutata? manco per sogno!
Certo, ma in quel caso il client non e` inchiodato sulla connect() 
finche` il server non chiama accept()? Ho sempre pensato che fosse 
cosi`...  :-(
Un'altra domanda: pensi che sui sistemi *nix funzioni esattamente allo 
stesso modo? Non ho ancora avuto tempo per provare...convinto di aver 
trovato un buco su Winsock...
Grazie tante!
-- Ale

 
figurati ;)
lb

 se il blocco dura un nulla ;D
OK, penso proprio di aver capito.
Eppure c'e` ancora qualcosa che mi lascia perplesso...
La chiamata alla funzione connect() non-bloccante dovrebbe durare almeno un 
epsilon meno della connect() bloccante. Di fatto, la connect() bloccante deve 
sempre aspettare almeno un qualche segnale di inizio dell'handshacking di 
connessione TCP, mentre la connect() non bloccante non deve aspettare niente.
Eppure ho la netta sensazione che la connect() non bloccante duri 
sensibilmente di piu` della corrispondente bloccante.
Ti sembra possibile?
Mi sa che mi devo mettere a misurare le prestazioni in termini di cicli di 
clock...
Grazie 1000,
-- Ale


Queste sono supposizioni. Per quello che ne sai la connect() non
bloccante a livello di kernel potrebbe contare cento cifre di pi-greco
prima di ritornare (al di là dell'esagerazione, magari deve settare
delle callback e/o allocare della memoria che la bloccante non
necessita).
Ciao!

 
divertiti ;D