Sto' scrivendo un server FTP in c sotto winxp di cui riporto sotto
il codice:


  • #include<winsock.h>
    #include<windows.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #pragma comment(lib, "ws2_32.lib")

    #define MAX_PORTE 6 //numero massimo di porte nel range porte apribili per il canale dati
    SOCKET s1,s2,s3,s4;
    WSADATA WsaData;
    struct sockaddr_in in1,in2,in3,in4;
    HKEY hKey;
    //variabili e buffer
    char buffer[100];
    int risposta[2]; //buffer contenente valore codice di risposta e numero di porta scelta per aprire canale dati
    int range_porte[6]={3267,3268,3269,3270,3271,3272}; //range di porte apribili per il canale dati
    //funzioni e procedure
    void connettiti1(void);
    int init_connetti(int porta);
    char *ricevi(char *buff,int lenght);
    char *rx_com(char *buff);
    int *comando(char *com, char *parametro);
    char buffer1[8];

    int main()
    {
    int x;
    for(x=1;x<3;x++)
    risposta[x]=0;
    while(1)
    {
    connettiti1();
    strncpy(buffer,"\n220 Server ftp\r\n\n",21);
    send(s2,buffer,strlen(buffer),0);
    do{
    switch(*comando("USER ","fabio"))
    {
    case 331:
    send(s2,"\n\r331 User required for fabio\n\r",strlen("\n\r331 User required for fabio\n\r"),0);
    break;
    case 440:
    send(s2,"\n\r440 Error login\n\r",strlen("\n\r440 Error login\n\r"),0);
    break;
    case 400:
    send(s2,"\n\r400 Unknow command\n\r",strlen("\n\r440 Unknow command\n\r"),0);
    break;
    }
    }while(*risposta==440 || *risposta==400);
    do{
    switch(*comando(" ","aaaaaaaa"))
    {
    case 440:
    send(s2,"\n\r440 Error login\n\r",strlen("\n\r440 Error login\n\r"),0);
    break;
    case 230:
    send(s2,"\n\r230 Welcome fabio",strlen("\n\r230 Welcome fabio"),0);
    send(s2,"\n\r230 User fabio login\n\r",strlen("\n\r230 User fabio login\n\r"),0);
    break;
    case 400:
    send(s2,"\n\r400 Unknow command\n\r",strlen("\n\r400 Unknow command\n\r"),0);
    break;
    }
    }while(*risposta==440 || *risposta==400);
    do{
    switch(*comando("PASV",0))
    {
    case 450:
    send(s2,"\n\r450 Impossible to open data connection",strlen("\n\r450 Impossible to open data connection"),0);
    break;
    case 220:
    send(s2,"\n\r220 data connection opened in port ",strlen("\n\r220 data connection opened in port "),0);
    switch(risposta[1])
    {
    case 3267:
    send(s2,"3267",strlen("3267"),0);
    break;
    case 3268:
    send(s2,"3268",strlen("3268"),0);
    break;
    case 3269:
    send(s2,"3269",strlen("3269"),0);
    break;
    case 3270:
    send(s2,"3270",strlen("3270"),0);
    break;
    case 3271:
    send(s2,"3271",strlen("3271"),0);
    break;
    case 3272:
    send(s2,"3272",strlen("3272"),0);
    break;
    }
    send(s2,"\n\r",strlen("\n\r"),0);
    strncpy(buffer,"\n220 Data connection created\r\n\n",21);
    send(s4,buffer,strlen(buffer),0);
    break;
    case 400:
    send(s2,"\n\r400 Unknow command\n\r",strlen("\n\r400 Unknow command\n\r"),0);
    break;
    }
    }while(*risposta==450 || *risposta==400);
    switch(*comando(0,0))
    {
    case 451:
    send(s2,"\n\rUnable to open file\n\r",strlen("\n\rUnable to open file\n\r"),0);
    break;
    case 420:
    send(s2,"\n\rCommand failure\n\r",strlen("\n\rCommand failure\n\r"),0);
    break;
    case 210:
    send(s2,"\n\rRequest success\n\r",strlen("\n\rRequest success\n\r"),0);
    break;
    }
    system("PAUSE");
    shutdown(s1,2);
    closesocket(s1);
    shutdown(s2,2);
    closesocket(s2);
    WSACleanup();
    }
    return(0);
    }


    void connettiti1(void)
    {
    int lenght;
    WSAStartup(0x0202,&WsaData);
    s1=socket(PF_INET,SOCK_STREAM,0);
    in1.sin_family=PF_INET;
    in1.sin_port=htons(21); //porta da usare
    in1.sin_addr.s_addr=INADDR_ANY;
    bind(s1,(struct sockaddr*)&in1,sizeof(struct sockaddr_in));
    lenght=sizeof(struct sockaddr);
    listen(s1,1);
    s2=accept(s1,(struct sockaddr*)&in2,(LPINT)&lenght);
    }

    //funzione di inizializzazione socket
    int init_connetti(int porta)
    {
    int lenght; //inizializza una socket su una delle porte di range_porte[]
    WSAStartup(0x0202,&WsaData);
    s3=socket(PF_INET,SOCK_STREAM,0);
    in3.sin_family=PF_INET;
    in3.sin_port=htons(porta); //porta da usare
    in3.sin_addr.s_addr=INADDR_ANY;
    int stato=bind(s3,(struct sockaddr*)&in3,sizeof(struct sockaddr_in));
    if(stato==0) //se la porta non e' collegata a nessun processo allora mettila in ascolto
    {
    lenght=sizeof(struct sockaddr);
    listen(s3,1);
    s4=accept(s3,(struct sockaddr*)&in4,(LPINT)&lenght);
    }
    return stato; //ritorna stato di bind()
    }


    char *ricevi(char *buff,int lenght)
    {
    int i;
    for(i=0;i<lenght+1;i++)
    {
    recv(s2,buff+i,1,0);
    }
    *(buff+i)='\0';
    return buff;
    }

    //funzione per l'esecuzione dei comandi FTP e il ritorno del codice di risposta
    int *comando(char *com, char *parametro)
    {
    int x;
    #define MAX 10000
    char array1[MAX];
    printf("\n*com=%s *parametro=%s",com,parametro);
    if(strncmp(ricevi(buffer,14),"USER ",4)==0)
    {
    printf("\n*buffer=%s",buffer+5);
    if(strncmp(buffer+10,parametro,4)==0)
    {
    printf("\n*buffer+10=%s",buffer+10);
    *risposta=331;
    return risposta;
    }
    else
    {
    printf("\n*buffer+5=%s",buffer+5);
    *risposta=440;
    return risposta;
    }
    }
    printf("\n*buffer=%s",buffer);
    if(strncmp(com," ",1)==0)
    {
    strncpy(buffer,"\nPassword for fabio: ",20);
    send(s2,buffer,strlen(buffer),0);
    if(strncmp(ricevi(buffer,8),parametro,8)==0)
    {
    *risposta=230;
    return risposta;
    }
    else
    {
    *risposta=440;
    return risposta;
    }
    }
    if(com=="PASV")
    {
    int i=0;
    if(strncmp(ricevi(buffer,4),com,4)==0)
    {
    for(x=0;x<MAX_PORTE+1;x++)
    {
    if(init_connetti(range_porte[x])==SOCKET_ERROR)
    {
    switch (WSAGetLastError())
    {
    case WSAEADDRINUSE:
    i++;
    continue;
    }
    }
    break;
    }
    if(i==MAX_PORTE+1)
    {
    *risposta=450;
    return risposta;
    }
    *risposta=220;
    *(risposta+1)=range_porte[x];
    return risposta;
    }
    else
    {
    *risposta=400;
    return risposta;
    }
    }
    if(!(strncmp(ricevi(buffer,4),"LIST",4)))
    {
    system("DIR C:\>file.txt"); //scarica il risultato del comando DIR su file
    FILE *fp=fopen("file.txt","w+");
    if(fp==NULL)
    {
    *risposta==451;
    return risposta;
    }
    //invia il file attraverso il canale dati
    while(!feof(fp))
    {
    switch((*fgets(array1,MAX+1,fp))) //leggi il file del risultato del comando DIR e mettito dentro ad array1[]
    {
    case 0:
    *risposta=451;
    return risposta;
    break;
    }
    }
    int sent=send(s4,array1,strlen(array1),0);
    fclose(fp);
    shutdown(s3,2);
    closesocket(s3);
    shutdown(s4,2);
    closesocket(s4);
    if(sent!=strlen(array1))
    {
    *risposta=420;
    return risposta;
    }
    else *risposta=210;return risposta;
    }
    *risposta=400;
    return risposta;
    }

    //funzione per la lettura dei parametri dei comandi
    char *rx_com(char *buff)
    {
    int i;
    for(i=0;(buff+i)!='\0';i++)
    {
    recv(s2,buff+i,1,0);
    }
    return buff;
    }



Una volta compilato ed esegito avvio telnet e digito --> ftp 127.0.0.1 avvio quindi una sessione FTP locale ed ottengo la seguente risposta:

Connessio a 127.0.0.1
220 Server ftp
Utente <127.0.0.1:<none>>: USER fabio ---> digito quindi "USER fabio"

ed ottengo:


  • 330 User required for fabio Connessione chiusa dall' host remoto


e mi ritorna quindi il prompt del dos:

  • C:\


Non capisco a questo punto perche nel momento in cui devo inserire la password mi chiude
la connessione senza permettermi di inserirla.
Nessuno mi puo' dare una mano a capire perche' mi chiude la connessione?
Ho seguito con il debugger fino alla sucessiva chiamata di recv() dentro alla funzione comando() ma fermandosi li chiude pure la connessione ma non capisco perche'.