recv перезаписать символ [] - PullRequest
0 голосов
/ 26 мая 2010

Я пытаюсь сделать небольшой клиент-серверный скрипт, как и многие другие, которые я делал в прошлом.
Но в этом у меня есть проблема. Лучше, если я отправлю код и вывод, который он мне даст.
Код:

#include <mysql.h> //not important now
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

//constant definition
#define SERVER_PORT 2121
#define LINESIZE 21

//global var definition
char victim_ip[LINESIZE], file_write[LINESIZE], hacker_ip[LINESIZE];

//function
void leggi (int); //not use now for debugging purpose
//void scriviDB (); //not important now

main () {

int sock, client_len, fd;

struct sockaddr_in server, client;

// transport end point
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  perror("system call socket fail");
  exit(1);
}

server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("10.10.10.1");
server.sin_port = htons(SERVER_PORT);

// binding address at transport end point
if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
  perror("system call bind fail");
  exit(1);
}

//fprintf(stderr, "Server open: listening.\n");
listen(sock, 5);

/* managae client connection */
while (1) {
  client_len = sizeof(client);
  if ((fd = accept(sock, (struct sockaddr *)&client, &client_len)) < 0) 
     { perror("accepting connection"); exit(1);  }

  strcpy(hacker_ip, inet_ntoa(client.sin_addr));
  printf("1 %s\n", hacker_ip); //debugging purpose
  //leggi(fd);

//////////////////////////
//receive client 
  recv(fd, victim_ip, LINESIZE, 0);
  victim_ip[sizeof(victim_ip)] = '\0';
  printf("2 %s\n", hacker_ip); //debugging purpose
  recv(fd, file_write, LINESIZE, 0);
  file_write[sizeof(file_write)] = '\0';
  printf("3 %s\n", hacker_ip); //debugging purpose
  printf("%s@%s for %s\n", file_write, victim_ip, hacker_ip);

  //send to client
  send(fd, hacker_ip, 40, 0); //now is hacker_ip for debug

/////////////////////////

  close(fd);

}//end while

exit(0);
} //end main

Клиент отправляет строку: ./send -i 10.10.10.4 -f filename.ext
поэтому скрипт отправляет -i (IP) и -f (FILE) на сервер.
Вот моя сторона сервера вывода:

1 10.10.10.6
2 10.10.10.6
3
filename.ext@10.10.10.4 для

Как вы видите, printf (3) и printf (ip, file, ip) терпят неудачу.
Я не знаю, как и где, но кто-то перезаписал мою строку hacker_ip.
Спасибо за вашу помощь! :)

Ответы [ 2 ]

3 голосов
/ 26 мая 2010

TCP предоставляет поток, а не пакеты. Таким образом, вам не гарантируется, что данные, которые вы отправляете с 1 вызов send () принимает 1 вызов recv () для получения. Это может занять несколько вызовов recv (), чтобы получить то, что отправил один вызов send (), или может потребоваться 1 вызов recv (), чтобы получить то, что отправлено несколько вызовов send () - каким-то образом вы должны справиться с этим.

В частности, вы должны проверить возвращаемое значение recv (), чтобы узнать, сколько байт вы получили, возможно, это может быть началом, так что вы по крайней мере не печатаете мусор в своих строках.

ssize_t bytes = recv(fd, victim_ip, LINESIZE, 0);
 if(bytes == 0) {
   //remote closed the connection, handle it
 } else if (bytes < 0) {
    //handle error
 } else {
   victim_ip[bytes] = '\0';
   printf("%s\n", victim_ip); 
}
1 голос
/ 26 мая 2010

Вы должны исправить строки как:

victim_ip[sizeof(victim_ip)] = '\0';

и

file_write[sizeof(file_write)] = '\0';

Это тот, который перезаписывает строку hacker_ip.

Записывает ноль после конца массива (sizeof(file_write) == LINE_SIZE). Если вы хотите записать сторожевой ноль, вы должны установить размерность массива еще на один символ, например file_write[LINE_SIZE+1].

Это исключение, оно должно работать. Для очень маленьких порций данных, таких как здесь (21 байт), маловероятно, что пакет будет разделен (стандартные кадры Ethernet составляют около 1400 байт). Но если вы сделали несколько посылок, они наверняка будут объединены в один пакет.

Было бы интересно увидеть код отправителя. Вы посылали полный буфер каждый раз? (должен смотреть на ваш recv ()).

...