Как получить URL с локального сервера без использования libcurl - PullRequest
0 голосов
/ 08 мая 2019

Я создал собственный HTTP-сервер, который обслуживает HTML-страницу с некоторым текстом, текстовое поле ввода для ввода команды и кнопку отправки. После получения отправки формы сервер должен выполнить данную команду и предоставить ответ, содержащий результаты.

Проблема, которую я не могу понять, состоит в том, как получить URL-адреса запросов на отправку формы, чтобы разобрать команду для запуска. В настоящее время реализовано, что сервер работает на localhost: 3838, и когда клиент просматривает этот URL-адрес, сервер правильно отвечает с помощью формы. Когда пользователь вводит (скажем) команду ls в текстовое поле и нажимает кнопку отправки «Выполнить», выдается запрос на localhost:3838/run?command=ls. Как я могу получить этот URL на сервере, чтобы разобрать и выполнить команду?

Вот текущий код сервера:

CwebServer.c

<code>#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

#define PORT "3838" //port being connected to 
#define MAXLEN 800
#define BACKLOG 10 //number of pending connections to be held in queue

//format of html page 

char header []= 
"HTTP/1.1 200 Ok\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
"<!DOCTYPE html>\r\n"
"<html>\n"
"<head>\n"
"<title>Web-Based Remote Command Server</title>\r\n"
"</head>\n"
"<body>\n\n";
char input []=
"<form action= \"/run\" method= \"GET\"> \n"
"Command: <input type=\"text\" size=\"100\" name=\"command\">\n"
"<input type=\"submit\" value=\"Run\">\n"
"</form>";
char output []=
"<p>Command that was run and testing this:</p>\n"
"<pre>Your server will include the command that was just run here.
\ п \ п» "

Стандартный вывод:

\ n" "
Your server will include the stdout results here.
\ n \ n" «

Стандартная ошибка:

\ n» "
Your server will include the stderr results here.
\ г \ п \ г \ п" " \ г \ п" " \ г \ п"; char * buff = header; void sigchld_handler (int s) { (Пустоты) с; // тихое предупреждение о неиспользуемой переменной // waitpid () может переписать errno, поэтому мы сохраняем и восстанавливаем int save_errno = errno; while (waitpid (-1, NULL, WNOHANG)> 0); errno = save_errno; } void * get_in_addr (struct sockaddr * sa) { if (sa-> sa_family == AF_INET) { return & (((struct sockaddr_in *) sa) -> sin_addr); } return & (((struct sockaddr_in6 *) sa) -> sin6_addr); } int main (void) { int sockfd; int new_fd; struct addrinfo hints; struct addrinfo * serverinfo; struct addrinfo * p; struct sockaddr_storage client_addr; socklen_t addrsize; struct sigaction sa; int yes = 1; char s [INET6_ADDRSTRLEN]; статус int; memset (& hints, 0, sizeof hints); // делает структуру пустой hints.ai_family = AF_UNSPEC; // IPv4 или v6 hints.ai_socktype = SOCK_STREAM; // Нужен тип TCP hints.ai_flags = AI_PASSIVE; // Заполните IP для нас // если не получается получить информацию об ошибке адреса if ((status = getaddrinfo (NULL, PORT, & hints, & serverinfo))! = 0) { fprintf (stderr, "getaddrinfo:% s \ n", gai_strerror (status)); возврат 1; } for (p = serverinfo; p! = NULL; p = p-> ai_next) { if ((sockfd = socket (p-> ai_family, p-> ai_socktype, p-> ai_protocol)) == -1) { perror ("сервер: сокет"); Продолжить; } if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR и & yes, sizeof (int)) == -1) { PError ( "setsockopt"); выход (1); } if (bind (sockfd, p-> ai_addr, p-> ai_addrlen) == -1) { близко (sockfd); perror ("server: bind"); Продолжить; } перерыв; } freeaddrinfo (serverinfo); if (p == NULL) { fprintf (stderr, "сервер: не удалось связать \ n"); выход (1); } if (listen (sockfd, BACKLOG) == -1) { PError ( "слушать"); выход (1); } sa.sa_handler = sigchld_handler; // пожинаем все мертвые процессы sigemptyset (& sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction (SIGCHLD, & sa, NULL) == -1) { PError ( "sigaction"); выход (1); } printf ("сервер: ожидание соединений .... \ n"); в то время как (1) { addrsize = sizeof client_addr; new_fd = accept (sockfd, (struct sockaddr *) & client_addr, & addrsize); if (new_fd == -1) { perror («Не принимал»); Продолжить; } inet_ntop (client_addr.ss_family, get_in_addr ((struct sockaddr *) & client_addr), s, sizeof s); printf ("сервер: получено соединение от% s \ n", s); если (! вилка ()) { близко (sockfd); int bufsize = 1024; char * buffer = malloc (bufsize); send (new_fd, header, bufsize, 0); // write (new_fd, "HTTP / 1.1 200 OK \ n", 16); // write (new_fd, "Content-length: 46 \ n", 19); // write (new_fd, "Content-type: text / html \ n \ n", 25);// write (new_fd, " \ n \ n Веб-страница CAvengers \ n \ n ", 46); if (send (new_fd, buffer, MAXLEN, 0) == -1) PError ( "отправить"); близко (new_fd); Выход (0); } близко (new_fd); } вернуть 0; }

1 Ответ

2 голосов
/ 08 мая 2019

Веб-серверы и клиенты обмениваются данными по протоколу HTTP. Вот что делает их веб серверами, а не какой-то другой. HTTP является протоколом запроса / ответа: клиент отправляет запрос на сервер , который содержит информацию о том, что он запрашивает , и сервер обрабатывает этот запрос, чтобы определить, как ответить.

Ваш конкретный сервер, похоже, намеревается реализовать HTTP 1.1 . Это не самая последняя версия протокола, но это нормально. Практически каждый HTTP-клиент в мире понимает этот диалект. Но у вас довольно миниатюрный сервер, отвечающий на каждое установленное соединение одним и тем же HTTP-ответом, даже если клиент фактически не отправляет HTTP-запрос.

Ваш вопрос: как получить URI запроса. Ответом является чтение его с клиента через подключенный сокет, возвращаемый accept(). Для этого подойдет функция read() или recv(). Формат, который вы должны ожидать от клиента, описан в спецификациях HTTP, которые я связал выше, но в очень кратко, вы должны ожидать, что запрос начнется с имени метода запроса (GET), по крайней мере один пробел, URI запроса и пара возврат каретки / перевод строки. Вам потребуется проанализировать URI запроса, чтобы различить начальный запрос формы и отправку формы, и в последнем случае вы также сможете анализировать параметры запроса.

ОБРАТИТЕ ВНИМАНИЕ, однако, хотя HTTP является сравнительно простым протоколом, он все же намного сложнее, чем я только что описал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...