Я изучаю сетевое программирование на C и пытался создать для wget игрушечную версию.
Однако, когда я запускаю программу, я получаю страницу с некоторыми последними символами в начале и в конце(В данном случае 0 и f43).
Программа содержит два файла .c и два .h.
Один для синтаксического анализа (наивного) адреса, а другой - для сетевого запроса ивыгрузить данные.
Вот файлы для разбора ввода:
url.h
#ifndef URL_H
#define URL_H
/* information of an URL*/
struct url_info
{
char* url; //full url
char* protocol; // protocol type: http, ftp, etc...
char* host; // host name
int port; //port number
char* path; //path
};
typedef struct url_info url_info;
static const char P_HTTP[] = "http";
void parse_url(char* url, url_info *info);
void exit_with_error(char* message);
void print_url_info(url_info info);
#endif //URL_H
url.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"url.h"
void parse_url(char* url, url_info *info)
{
// url format: [http://]<hostname>[:<port>]/<path>
char *full_url = malloc((strlen(url) + 1) * sizeof(char));
char *protocol;
char *path;
char *host;
int port;
strcpy(full_url, url);
info->url = full_url;
char *protocol_token = strstr(url, "://");
if (protocol_token){
protocol = url;
*protocol_token = '\0';
url = protocol_token + 3;
} else {
protocol = "http";
}
info->protocol = protocol;
char *port_token = strstr(url, ":");
char *path_token = strstr(url, "/");
if (port_token && port_token < path_token){
port = atoi(port_token + 1);
*port_token = '\0';
} else {
port = 80;
}
info->port = port;
if (path_token){
*path_token = '\0';
host = url;
path = path_token + 1;
info->host = host;
info->path = path;
} else {
exit_with_error("No trailing /.");
}
}
void print_url_info(url_info info){
printf("The URL contains following information: \n");
printf("Full url:\t%s\n", info.url);
printf("Protocol type:\t%s\n", info.protocol);
printf("Host name:\t%s\n", info.host);
printf("Port No.:\t%d\n", info.port);
printf("Path:\t\t%s\n", info.path);
}
void exit_with_error(char *message)
{
fprintf(stderr, "%s\n", message);
exit(EXIT_FAILURE);
}
Вот файлы для выполнения запроса
wgetX.h
#ifndef WGETX_H_
#define WGETX_H_
#define B_SIZE 1024 * 5000
void write_data(const char *path, const char *data);
char* download_page(url_info info, char *buff);
char* http_get_request(char* path, char* host);
char* read_http_reply(char* recv_buf_t);
unsigned long ipfromhost(const char *host);
#endif
wgetX.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "url.h"
#include "wgetX.h"
int main(int argc, char* argv[])
{
url_info info;
if (argc != 2) {
exit_with_error("The wgetX must have exactly 1 parameter as input. \n");
}
char *url = argv[1];
parse_url(url, &info);
char *buf;
buf = malloc(sizeof(char)*B_SIZE);
bzero(buf, B_SIZE);
download_page(info, buf);
printf("%s", buf);
free(buf);
return (EXIT_SUCCESS);
}
char* download_page(url_info info, char *buf)
{
struct sockaddr_in dest;
int len, sz, mysocket;
char *request = http_get_request(info.path, info.host);
mysocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = ipfromhost(info.host);
dest.sin_port = htons(info.port);
connect(mysocket, (struct sockaddr *)&dest, sizeof(struct sockaddr));
send(mysocket, request, strlen(request), 0);
len = 0;
sz = 0;
do {
len = recv(mysocket, buf + sz, B_SIZE - sz, 0);
if (len == -1) {continue;}
sz += len;
} while (len > 0);
*(buf + sz) = '\0';
close(mysocket);
return buf;
}
char* http_get_request(char* path, char* host) {
char * request_buffer = (char *) malloc(1024);
memset(request_buffer, 0, sizeof(*request_buffer));
snprintf(request_buffer, 1024, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",
path, host);
return request_buffer;
}
unsigned long ipfromhost(const char *host){
struct in_addr **addr_list;
struct hostent *he;
if ((he = gethostbyname(host)) != NULL){
addr_list = (struct in_addr **) he->h_addr_list;
int i;
for (i = 0; addr_list[i] != NULL; i++){
return addr_list[i]->s_addr;
}
exit_with_error("Couldn't resolve host to ip adress\n");
return 0;
} else {
exit_with_error("Couldn't resolve host to ip adress\n");
return 0;
}
}
Makefile
LINK_TARGET = wgetX
OBJS = \
wgetX.o \
url.o
REBUILDABLES = $(OBJS) $(LINK_TARGET)
all : $(LINK_TARGET)
clean:
rm -f $(REBUILDABLES)
$(LINK_TARGET) : $(OBJS)
cc -g -o $@ $^
%.o : %.c
cc -g -Wall -o $@ -c $<
wgetX.o : wgetX.h url.h
url.o : url.h
При выполнении программы по одному конкретному URL, я получаю вывод html, отличный от исходного кода (какнашел в хроме).Я получаю мусорные символы: ноль в конце и «f43» как раз перед началом html
Команды
make clean
make
./wgetX http://www.google.com/
Вывод
Я получил ответное сообщение http с кодом состояния и всем и только что до этого "