send() и puts() смешаны вместе (программирование FTP-сервера на C)
Вопрос
Я создаю FTP-сервер на C.На стороне клиента я использую FileZilla.Мой код пока содержит только часть квитирования.
Проблема, с которой я столкнулся, заключается в том, что строки, которые я распечатываю для терминала, отправляются в FileZilla.Мой вопрос в том, как я могу разделить эти две вещи, я попробовал пару вещей, но ни одна из них не дает правильного результата.
Это только часть моего кода, но на мой вопрос, полезна ли эта часть:
while (FOREVER){
addr_size = sizeof their_addr;
newfd = accept(listener, (struct sockaddr*) &their_addr, &addr_size);
if (newfd == -1){
perror("accept");
continue;
}
if ((send(newfd, "220 JEDI FTP is ready", 50, 0)) <= 0)
perror("error sending");
puts("connection established");
puts("waiting for user & connection");
while (!login){
// username
if (!user){
if ((recv(newfd, buffer, BUFFCON, 0)) <= 0){
puts("error receiving username");
}
else{
if (strstr(buffer, "USER") != NULL){
if (strstr(buffer, name) != NULL){
send(newfd, "331 password required", 50, 0);
puts("username correct");
user = 1;
}
else{
puts("username incorrect");
send(newfd, "430 username incorrect", 50, 0);
}//else
}//if
}//else
}//if user
И это выходные данные в FileZilla:
- Статус:Adres bepalen van localhost
- Статус:Verbinden met [::1]:21...
- Статус:Verbinding aangemaakt, welkomstbericht afwachten...
- Антворд:220 JEDI FTP готов
- Коммандос:ПОЛЬЗОВАТЕЛЬ yoda
- Антворд:установленное соединение
- Фут:Kan niet verbinden met server
Таким образом, вместо отправки "требуется пароль 331" он отправляет "установлено соединение".
Надеюсь, вы сможете помочь мне с этим, большое спасибо.
Решение
Проблема в том, что ваш len
параметр для send
слишком велик. send
не имеет понятия о строках, заканчивающихся нулем;он работает только с необработанными последовательностями байтов.Итак, звонок send(newfd, "220 JEDI FTP is ready", 50, 0)
отправляет строку "220 JEDI FTP is ready"
, а затем все, что происходит, всплывает в памяти после этого.Технически, это неопределенное поведение, так буквально что угодно может произойти (обычно сбой сегмента).В вашем случае, потому что постоянные литеральные строки обычно хранятся последовательно в памяти, send
читает заданную строку, а затем читает другую строку после нее.
То, что вы хотите сделать, это Только отправьте точную строку (для которой, кстати, нужна последовательность CR-LF \r\n
после каждой команды).Ни больше, ни меньше.Вы можете реализовать sends
функция для отправки строки следующим образом:
ssize_t sends(int fd, const char *str)
{
size_t len = strlen(str);
return send(fd, str, len, 0);
}
Также обратите внимание, что отправленные данные делают нет включите нулевой ограничитель, поскольку TCP-пакет определяет размер строки.