Написать простенький веб-сервер и клиент к нему - C#
Формулировка задачи:
Доброе всем время суток. Мне нужно написать простенький веб-сервер и клиент к нему. Клиент отправляет GET-запрос на сервер, сервер посылает в ответ в виде XML. Далее XML парсится и его значения переходят в RichTextBox'ы.
Веб-сервер я стянул отсюда http://habrahabr.ru/post/120157/
Вот код:
Вот код моего недо-клиента, который должен получать и обрабатывать ответ сервера. Я слабо представляю, как это должно выглядеть, поэтому просто попытался написать нечто, что будет считывать xml-файл и раскидывать его значения по тектбоксам.
По идее, нужно написать что-то вроде:
вот сам xml:
Проблема в том, что я не представляю себе, что нужно передать серверу в качестве запроса в GET, и как сервер должен передать XML-код мне обратно, а я считать его.
В гугле был, похожие темы видел, но не докурил, не могу понять сам принцип, прошу помощи в общем)
Листинг программы
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Net.Sockets;
- using System.Net;
- using System.Threading;
- using System.Text.RegularExpressions;
- using System.IO;
- using System.Xml.Linq;
- namespace HTTPServer
- {
- // Класс-обработчик клиента
- class Client
- {
- // Отправка страницы с ошибкой
- private void SendError(TcpClient Client, int Code)
- {
- // Получаем строку вида "200 OK"
- // HttpStatusCode хранит в себе все статус-коды HTTP/1.1
- string CodeStr = Code.ToString() + " " + ((HttpStatusCode)Code).ToString();
- // Код простой HTML-странички
- string Html = "<html><body><h1>" + CodeStr + "</h1></body></html>";
- // Необходимые заголовки: ответ сервера, тип и длина содержимого. После двух пустых строк - само содержимое
- string Str = "HTTP/1.1 " + CodeStr + "\nContent-type: text/html\nContent-Length:" + Html.Length.ToString() + "\n\n" + Html;
- // Приведем строку к виду массива байт
- byte[] Buffer = Encoding.ASCII.GetBytes(Str);
- // Отправим его клиенту
- Client.GetStream().Write(Buffer, 0, Buffer.Length);
- // Закроем соединение
- Client.Close();
- }
- // Конструктор класса. Ему нужно передавать принятого клиента от TcpListener
- public Client(TcpClient Client)
- {
- // Объявим строку, в которой будет хранится запрос клиента
- string Request = "";
- // Буфер для хранения принятых от клиента данных
- byte[] Buffer = new byte[1024];
- // Переменная для хранения количества байт, принятых от клиента
- int Count;
- // Читаем из потока клиента до тех пор, пока от него поступают данные
- while ((Count = Client.GetStream().Read(Buffer, 0, Buffer.Length)) > 0)
- {
- // Преобразуем эти данные в строку и добавим ее к переменной Request
- Request += Encoding.ASCII.GetString(Buffer, 0, Count);
- // Запрос должен обрываться последовательностью \r\n\r\n
- // Либо обрываем прием данных сами, если длина строки Request превышает 4 килобайта
- // Нам не нужно получать данные из POST-запроса (и т. п.), а обычный запрос
- // по идее не должен быть больше 4 килобайт
- if (Request.IndexOf("\r\n\r\n") >= 0 || Request.Length > 4096)
- {
- break;
- }
- }
- // Парсим строку запроса с использованием регулярных выражений
- // При этом отсекаем все переменные GET-запроса
- Match ReqMatch = Regex.Match(Request, @"^\w+\s+([^\s\?]+)[^\s]*\s+HTTP/.*|");
- // Если запрос не удался
- if (ReqMatch == Match.Empty)
- {
- // Передаем клиенту ошибку 400 - неверный запрос
- SendError(Client, 400);
- return;
- }
- // Получаем строку запроса
- string RequestUri = ReqMatch.Groups[1].Value;
- // Приводим ее к изначальному виду, преобразуя экранированные символы
- // Например, "%20" -> " "
- RequestUri = Uri.UnescapeDataString(RequestUri);
- // Если в строке содержится двоеточие, передадим ошибку 400
- // Это нужно для защиты от URL типа [url]http://example.com/file.txt[/url]
- if (RequestUri.IndexOf("..") >= 0)
- {
- SendError(Client, 400);
- return;
- }
- // Если строка запроса оканчивается на "/", то добавим к ней index.html
- if (RequestUri.EndsWith("/"))
- {
- RequestUri += "index.html";
- //RequestUri += "index.xml";
- }
- string FilePath = "www/" + RequestUri;
- // Если в папке www не существует данного файла, посылаем ошибку 404
- if (!File.Exists(FilePath))
- {
- SendError(Client, 404);
- return;
- }
- // Получаем расширение файла из строки запроса
- string Extension = RequestUri.Substring(RequestUri.LastIndexOf('.'));
- // Тип содержимого
- string ContentType = "";
- // Пытаемся определить тип содержимого по расширению файла
- switch (Extension)
- {
- case ".htm":
- case ".html":
- ContentType = "text/html";
- break;
- case ".css":
- ContentType = "text/stylesheet";
- break;
- case ".js":
- ContentType = "text/javascript";
- break;
- case ".jpg":
- ContentType = "image/jpeg";
- break;
- case ".jpeg":
- case ".png":
- case ".gif":
- ContentType = "image/" + Extension.Substring(1);
- break;
- default:
- if (Extension.Length > 1)
- {
- ContentType = "application/" + Extension.Substring(1);
- }
- else
- {
- ContentType = "application/unknown";
- }
- break;
- }
- // Открываем файл, страхуясь на случай ошибки
- FileStream FS;
- try
- {
- FS = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
- }
- catch (Exception)
- {
- // Если случилась ошибка, посылаем клиенту ошибку 500
- SendError(Client, 500);
- return;
- }
- // Посылаем заголовки
- string Headers = "HTTP/1.1 200 OK\nContent-Type: " + ContentType + "\nContent-Length: " + FS.Length + "\n\n";
- byte[] HeadersBuffer = Encoding.ASCII.GetBytes(Headers);
- Client.GetStream().Write(HeadersBuffer, 0, HeadersBuffer.Length);
- // Пока не достигнут конец файла
- while (FS.Position < FS.Length)
- {
- // Читаем данные из файла
- Count = FS.Read(Buffer, 0, Buffer.Length);
- // И передаем их клиенту
- Client.GetStream().Write(Buffer, 0, Count);
- }
- // Закроем файл и соединение
- FS.Close();
- Client.Close();
- }
- }
- class Server
- {
- TcpListener Listener; // Объект, принимающий TCP-клиентов
- // Запуск сервера
- public Server(int Port)
- {
- Listener = new TcpListener(IPAddress.Any, Port); // Создаем "слушателя" для указанного порта
- Listener.Start(); // Запускаем его
- // В бесконечном цикле
- while (true)
- {
- // Принимаем нового клиента
- TcpClient Client = Listener.AcceptTcpClient();
- // Создаем поток
- Thread Thread = new Thread(new ParameterizedThreadStart(ClientThread));
- // И запускаем этот поток, передавая ему принятого клиента
- Thread.Start(Client);
- }
- }
- static void ClientThread(Object StateInfo)
- {
- // Просто создаем новый экземпляр класса Client и передаем ему приведенный к классу TcpClient объект StateInfo
- new Client((TcpClient)StateInfo);
- }
- // Остановка сервера
- ~Server()
- {
- // Если "слушатель" был создан
- if (Listener != null)
- {
- // Остановим его
- Listener.Stop();
- }
- }
- static void Main(string[] args)
- {
- // Создадим новый сервер на порту 88
- new Server(88);
- }
- }
- }
Листинг программы
- private void button2_Click(object sender, EventArgs e)
- {
- var doc = XDocument.Load(@"C:\XMLFile1.xml"); //если запустить так, все отлично парсится
- //var doc = XDocument.Load(@"http://127.0.0.1:88/index.xml"); /*а если так, то запускается, но не работает: "The server committed a protocol violation. Section=ResponseStatusLine" */
- label3.Text = (doc.Root.Element("incident").Element("category").Attribute("name").Value);
- richTextBox1.Text = (doc.Root.Element("incident").Element("description").Value);
- richTextBox2.Text = (doc.Root.Element("incident").Element("place").Attribute("x").Value);
- richTextBox3.Text = (doc.Root.Element("incident").Element("place").Attribute("y").Value);
- richTextBox4.Text = (doc.Root.Element("incident").Element("place").Attribute("street").Value);
- richTextBox5.Text = (doc.Root.Element("incident").Element("place").Attribute("numhome").Value);
- richTextBox6.Text = (doc.Root.Element("incident").Element("place").Attribute("numflat").Value);
- textBox2.Visible = true;
- timer1.Enabled = true;
- }
Листинг программы
- private void button1_Click(object sender, EventArgs e)
- {
- try
- {
- var url = string.Format(@"http://{0}/", textBox1.Text);
- System.Net.WebRequest reqGET = System.Net.WebRequest.Create(url);
- var resp = reqGET.GetResponse();
- System.IO.Stream stream = resp.GetResponseStream();
- label5.Text = (new System.IO.StreamReader(stream)).ReadToEnd();
- }
- catch (WebException ea)
- {
- //MessageBox.Show("Ошибка");
- label1.Text = (ea.GetType().ToString()); //что-то типа лога с ошибками
- }
- }
Листинг программы
- <?xml version="1.0" encoding="utf-8"?>
- <result>
- <incident id="12323">
- <category id="12" name="North"/>
- <description>
- TEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXT
- </description>
- <place x="78.34534" y="56.4564566" street="Lenina" numhome="387" numflat="73"/>
- </incident>
- </result>
Решение задачи: «Написать простенький веб-сервер и клиент к нему»
textual
Листинг программы
- private void button1_Click(object sender, EventArgs e)
- {
- TcpClient tcpClient;
- NetworkStream networkStream;
- StreamReader streamReader;
- StreamWriter streamWriter;
- try
- {
- var url = string.Format(@"http://{0}/", textBox1.Text); //считали значение URL из текстбокса
- System.Net.WebRequest reqGET = System.Net.WebRequest.Create(url); //постали get-запрос на основе URL
- var resp = reqGET.GetResponse(); // получили ответ
- System.IO.Stream stream = resp.GetResponseStream(); // ?
- var nov = new System.IO.StreamReader((stream), Encoding.UTF8);
- label5.Text = (new System.IO.StreamReader(stream)).ReadToEnd(); // сюда по идее должна вставлять та самая передаваемая строчка, однако catch подхватывает ошибку и ничего не происходит
- }
- catch (WebException ea)
- {
- label1.Text = (ea.GetType().ToString());
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д