send() e puts() são misturados, (programação de um servidor de FTP em C)
Pergunta
Eu estou fazendo um servidor de FTP em C.No lado do cliente, estou usando o FileZilla.Meu código até agora só contém a saudação parte.
O problema que eu tenho é que as cadeias de caracteres de impressão para o terminal de são enviados para o programa FileZilla.A minha pergunta é como posso manter esses dois separados, eu tentei algumas coisas, mas nenhum deles fornece o resultado correto.
Esta é apenas uma parte do meu código, mas para a minha pergunta é esta a parte útil:
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
E esta é a saída do FileZilla:
- Status:Adres bepalen van localhost
- Status:Verbinden atendidas [::1]:21...
- Status:Verbinding aangemaakt, welkomstbericht afwachten...
- Antwoord:220 JEDI FTP está pronto
- Commando:USUÁRIO yoda
- Antwoord:conexão estabelecida
- Fout:Kan niet verbinden conheceu do servidor
Assim, em vez de enviar "331 necessária palavra-passe" envia "conexão estabelecida"
Espero que você possa me ajudar com isso, muito Obrigado.
Solução
O problema é que o seu len
parâmetro para send
é muito grande. send
não tem nenhum conceito de seqüências de terminação nula;ele só trabalha com matérias-primas de seqüências de bytes.Portanto, a chamada send(newfd, "220 JEDI FTP is ready", 50, 0)
envia a seqüência de caracteres "220 JEDI FTP is ready"
, e , em seguida, tudo o que acontece vem na memória depois.Tecnicamente, isso é comportamento indefinido, portanto, literalmente nada pode acontecer (geralmente um segfault).No seu caso, devido a constantes cadeias de caracteres literais são normalmente armazenados seqüencialmente na memória, send
a leitura é determinada a seqüência de caracteres e, em seguida, a leitura de uma seqüência diferente depois.
O que você quer fazer é apenas enviar a seqüência exata (que, por sinal, precisa do CR-LF sequência \r\n
após cada comando).Nem mais, nem menos.Você pode implementar um sends
função para enviar uma seqüência de caracteres, como por exemplo:
ssize_t sends(int fd, const char *str)
{
size_t len = strlen(str);
return send(fd, str, len, 0);
}
Observe também que os dados enviados não não incluir null-o exterminador do futuro, porque o pacote TCP especifica o tamanho da seqüência de caracteres.