2010-05-26 2 views
0

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

#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("%[email protected]%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 -f 10.10.10.4 имяфайла.рсш
так скрипт отправки -i (IP) и -f (FILE) на сервере.
Вот мой выход на стороне сервера:

1 10.10.10.6
2 10.10.10.6
[email protected] для

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

ответ

3

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); 
} 
+0

Отлично, это работает! :) Спасибо большое! – Possa

1

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

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()).

+0

Я пробовал, но не работал. – Possa

+0

@ Посса: Что вы на самом деле пытались? Проблема действительно очевидна, поэтому вы, скорее всего, не выполнили свою коррекцию (или, что еще хуже, отправитель фиктивный или, по крайней мере, не соответствует получателю). В любом случае установка конечного нуля при возвращаемом значении позиции recv() не должна иметь никакого эффекта. Если код отправителя правильный, возвращаемое значение будет LINESIZE, и оно будет точно таким же, как и ваш код. Если recv получит ошибку, то это значение возврата может быть 0 или -1 вместо LINESIZE, но в этом случае вы не получите свои данные.В противном случае такой короткий буфер никогда не будет усечен. Проверьте. – kriss

 Смежные вопросы

  • Нет связанных вопросов^_^