tftp-клиент не получает от сервера (отправляет на неверный порт)

Я пишу свой собственный TFTP-клиент. Клиент написан на c++ (частично на c) и работает в системе unix (стабильная версия Linux Debian).

Вот моя проблема:

Я могу отправить свой запрос на чтение (RRQ) на TFTP-сервер (открытый TFTP-сервер в Windows XP). TFTP-сервер получает RRQ, но не может отправить ответ.

На стороне сервера я вижу это сообщение: Client 192.168.1.110:55239 C:\OpenTFTPServer\test.txt, Ошибка связи

Но порт 55239 — это не тот порт, который я определил в своем TFTP-клиенте.

Вот мои части кода:

  • установить адреса клиента и сервера:

    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(servport); // servport=69
    servaddr.sin_addr.s_addr = inet_addr("192.168.1.152"); 
    
    memset(&cliaddr,0,sizeof(cliaddr));
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(cliport); // cliport=13337
    cliaddr.sin_addr.s_addr = inet_addr("192.168.1.110");
    
  • подключить и привязать:

    if (connect(serv, (struct sockaddr *) &servaddr, serv_length) < 0)
    {
        bail("Unable to connect with the server!");
    }
    if(bind(cli, (struct sockaddr *)&cliaddr, cli_length)<0)
    {
        bail("Unable to bind to adr & port!");
    }
    
  • создать запрос TFTP:

    memset( &cBuf1, 0, sizeof cBuf1);
    rdwrFrame = (struct tftp_wr_rq *)&cBuf1;
    rdwrFrame->opcode=htons(1);
    rdwrFrame->data={'t','e','s','t','.','t','x','t','\0','o','c','t','e','t','\0'};
    
  • отправить TFTP-запрос:

    if (sendto (serv,cBuf1,19,0,(struct sockaddr *)&servaddr,serv_length) < 0)
    {
        bail ("Send the first requirment Frame error -- UDP");
    }
    

Вот мой вопрос:

Что я делаю не так, что TFTP-сервер получает не тот порт? Я думал, что это должно быть установлено с помощью cliaddr.sin_port = htons(cliport);

Спасибо за помощь и с уважением Рико

Ответ:

Моя проблема заключалась в том, что я объединил неправильные сокеты с неправильными адресными структурами.

Вот мои рабочие части кода:

  • создать сокеты:

    serv = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (serv < 0)
    {
        bail("Unable to create socket tx!");
    }
    
    cli = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (cli < 0)
    {
        bail("Unable to create socket rx!");
    }
    
  • установить адреса клиента и сервера:

    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(servport);
    servaddr.sin_addr.s_addr = inet_addr("192.168.1.152"); 
    
    memset(&cliaddr,0,sizeof(cliaddr));
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(cliport);
    cliaddr.sin_addr.s_addr = inet_addr("192.168.1.110");
    
  • подключить и привязать:

    if(bind(cli, (struct sockaddr *)&cliaddr, cli_length)<0)
    {
        bail("Unable to bind to adr & port!");
    }
    
    if (connect(serv, (struct sockaddr *) &servaddr, serv_length) < 0)
    {
        bail("Unable to connect with the server!");
    }
    
  • создать TFTP-запрос:

    memset( &cBuf1, 0, sizeof cBuf1);
    rdwrFrame = (struct tftp_wr_rq *)&cBuf1;
    rdwrFrame->opcode=htons(1);
    rdwrFrame->data={'t','e','s','t','.','t','x','t',(char)0,'o','c','t','e','t',(char)0};
    
  • отправить TFTP-запрос:

    if (sendto (cli,cBuf1,19,0,(struct sockaddr *)&servaddr,serv_length) < 0)
    {
        bail ("Send the first requirment Frame error -- UDP");
    }
    
  • получить данные:

    recvfrom(cli,cBuf2,19,0,(struct sockaddr *)&cliaddr,(socklen_t*)&cli_length);
    

person i3luefire    schedule 21.12.2012    source источник
comment
Привет, Рико, как определяется/устанавливается переменная cliport?   -  person GMasucci    schedule 21.12.2012
comment
Привет, cliport беззнаковый короткий --› беззнаковый короткий clipport = 13337   -  person i3luefire    schedule 21.12.2012
comment
Вы случайно не пробовали прямую проверку cliaddr.sin_port = 13337?   -  person GMasucci    schedule 21.12.2012
comment
Я пробовал это: cliaddr.sin_port=13337; и это: cliaddr.sin_port=htons(13337);, но я все еще вижу случайный порт при просмотре сервера   -  person i3luefire    schedule 21.12.2012
comment
также должна быть возможность указать sendto (serv,cBuf1,19,0,(struct sockaddr*)&servaddr,serv_length), но для получения он должен быть в формате connect(intValHere,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0). Я думаю, что проблема может заключаться в формате подключения. Думаю, вы просто пропустили sizeof в соединении. В любом случае, поздно я знаю, и я могу расширить или дать более подробный ответ.   -  person GMasucci    schedule 21.12.2012
comment
К вашему комментарию: serv_length - это значение sizeof(serv_addr) - Хорошо, я понял, как отправить пакет с правильным исходным портом. Я делаю ошибку, создавая 2 сокета, сокет rx и tx (cli и serv), затем я привязываюсь к сокету cli и подключаюсь к сокету serv. Таким образом, сообщение было отправлено без определенного порта и получило случайное число. Теперь проблема в том, что я все еще не получаю ответа в своем клиенте и все еще получаю сообщение об ошибке связи из-за недоступного порта.   -  person i3luefire    schedule 21.12.2012
comment
Вы пытаетесь сделать клиент, который может и отправлять, и получать?   -  person GMasucci    schedule 21.12.2012
comment
Да, клиент должен отправлять и получать. Из-за того, как работает TFTP. Клиент отправляет запрос на чтение и получает пакет данных, затем он отправляет пакет подтверждения и получает следующий пакет данных и так далее...   -  person i3luefire    schedule 21.12.2012
comment
Итак, вы установили clientRcvPort и clientSendPort, а также servRcvPort и servSendPort? на клиенте у вас будет clientRcvPort = mychoice clientSendPort = servRcvPort на сервере servRcvPort = clientSendPort servSendPort = clientRcvPort не настоящий код, просто для иллюстрации, если эти порты не совпадают в этом порядке, тогда вы можете получить что-то сломанное   -  person GMasucci    schedule 21.12.2012
comment
Я нашел проблему. Также была проблема с неправильной комбинацией сокета/адреса. Я добавлю свое полное решение к моему вопросу, потому что я не могу ответить на него сам, пока не пройдет 5 часов.   -  person i3luefire    schedule 21.12.2012


Ответы (1)


Я добавил ответ отдельно, поэтому никому не нужно искать его в исходном сообщении.

Ответ:

Моя проблема заключалась в том, что я объединил неправильные сокеты с неправильными адресными структурами.

Вот мои рабочие части кода:

  • создать сокеты:

    serv = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (serv < 0)
    {
        bail("Unable to create socket tx!");
    }
    
    cli = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (cli < 0)
    {
        bail("Unable to create socket rx!");
    }
    
  • установить адреса клиента и сервера:

    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(servport);
    servaddr.sin_addr.s_addr = inet_addr("192.168.1.152"); 
    
    memset(&cliaddr,0,sizeof(cliaddr));
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(cliport);
    cliaddr.sin_addr.s_addr = inet_addr("192.168.1.110");
    
  • подключить и привязать:

    if(bind(cli, (struct sockaddr *)&cliaddr, cli_length)<0)
    {
        bail("Unable to bind to adr & port!");
    }
    
    if (connect(serv, (struct sockaddr *) &servaddr, serv_length) < 0)
    {
        bail("Unable to connect with the server!");
    }
    
  • создать TFTP-запрос:

    memset( &cBuf1, 0, sizeof cBuf1);
    rdwrFrame = (struct tftp_wr_rq *)&cBuf1;
    rdwrFrame->opcode=htons(1);
    rdwrFrame->data={'t','e','s','t','.','t','x','t',(char)0,'o','c','t','e','t',(char)0};
    
  • отправить TFTP-запрос:

    if (sendto (cli,cBuf1,19,0,(struct sockaddr *)&servaddr,serv_length) < 0)
    {
        bail ("Send the first requirment Frame error -- UDP");
    }
    
  • получить данные:

    recvfrom(cli,cBuf2,19,0,(struct sockaddr *)&cliaddr,(socklen_t*)&cli_length);
    
person i3luefire    schedule 09.04.2014