send()とputs()は一緒に混合されます(CでFTPサーバをプログラム)
質問
私はFTPサーバーをCで作成しています。クライアント側でFileZillaを使用しています。これまでのコードには、ハンドシェイク部分のみが含まれています。
私が持っている問題は、ターミナルに印刷する文字列がfilezillaに送信されることです。 私の質問は、これら2つを別々に保つことができます、私はいくつかのことを試しましたが、それらのどれも正しい結果を与えませんでした。
これは私のコードの一部ですが、私の質問のためにこれは役に立つ部分です:
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 ...
- ステータス:動き出しAangemaakt、Welkomstbericht Afwachten ...
- Antworord:220 Jedi FTPの準備ができている
- Commando:ユーザーヨーダ
- Antwoord:接続確立
- FOUT:Kan Niet Verbinden Met Server
「331パスワードが必要な」を送信する代わりに「接続確立」
を送信します。これで私を助けることができることを願って、たくさんありがとう。
解決
問題は、len
のsend
パラメータが大きすぎることです。 send
には、ヌル終端文字列の概念はありません。それはバイトの生のシーケンスでのみ機能します。そのため、Call send(newfd, "220 JEDI FTP is ready", 50, 0)
は文字列"220 JEDI FTP is ready"
を送信し、次にそれ以降のメモリに入ってくるものは何でもします。技術的には、これは未定義の動作です。文字通りが発生する可能性があります(通常はSegFault)。あなたの場合、定数のリテラル文字列は通常メモリに順番に保存されるため、send
は指定された文字列を読み、次にそれ以降の文字列を読み取っています。
あなたがやりたいことのみ正確な文字列を送信すること(つまり、各コマンドの後にCR-LFシーケンス\r\n
を必要とします)。もう少し、それほどない。 SOのような文字列を送信するためのsends
関数を実装できます。
ssize_t sends(int fd, const char *str)
{
size_t len = strlen(str);
return send(fd, str, len, 0);
}
.
TCPパケットは文字列のサイズを指定しているため、送信されていないデータはNULL-TERKINATERを含みます。