Написать простенький веб-сервер и клиент к нему - C#

Узнай цену своей работы

Формулировка задачи:

Доброе всем время суток. Мне нужно написать простенький веб-сервер и клиент к нему. Клиент отправляет GET-запрос на сервер, сервер посылает в ответ в виде XML. Далее XML парсится и его значения переходят в RichTextBox'ы. Веб-сервер я стянул отсюда http://habrahabr.ru/post/120157/ Вот код:
Листинг программы
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Net.Sockets;
  5. using System.Net;
  6. using System.Threading;
  7. using System.Text.RegularExpressions;
  8. using System.IO;
  9. using System.Xml.Linq;
  10. namespace HTTPServer
  11. {
  12. // Класс-обработчик клиента
  13. class Client
  14. {
  15. // Отправка страницы с ошибкой
  16. private void SendError(TcpClient Client, int Code)
  17. {
  18. // Получаем строку вида "200 OK"
  19. // HttpStatusCode хранит в себе все статус-коды HTTP/1.1
  20. string CodeStr = Code.ToString() + " " + ((HttpStatusCode)Code).ToString();
  21. // Код простой HTML-странички
  22. string Html = "<html><body><h1>" + CodeStr + "</h1></body></html>";
  23. // Необходимые заголовки: ответ сервера, тип и длина содержимого. После двух пустых строк - само содержимое
  24. string Str = "HTTP/1.1 " + CodeStr + "\nContent-type: text/html\nContent-Length:" + Html.Length.ToString() + "\n\n" + Html;
  25. // Приведем строку к виду массива байт
  26. byte[] Buffer = Encoding.ASCII.GetBytes(Str);
  27. // Отправим его клиенту
  28. Client.GetStream().Write(Buffer, 0, Buffer.Length);
  29. // Закроем соединение
  30. Client.Close();
  31. }
  32. // Конструктор класса. Ему нужно передавать принятого клиента от TcpListener
  33. public Client(TcpClient Client)
  34. {
  35. // Объявим строку, в которой будет хранится запрос клиента
  36. string Request = "";
  37. // Буфер для хранения принятых от клиента данных
  38. byte[] Buffer = new byte[1024];
  39. // Переменная для хранения количества байт, принятых от клиента
  40. int Count;
  41. // Читаем из потока клиента до тех пор, пока от него поступают данные
  42. while ((Count = Client.GetStream().Read(Buffer, 0, Buffer.Length)) > 0)
  43. {
  44. // Преобразуем эти данные в строку и добавим ее к переменной Request
  45. Request += Encoding.ASCII.GetString(Buffer, 0, Count);
  46. // Запрос должен обрываться последовательностью \r\n\r\n
  47. // Либо обрываем прием данных сами, если длина строки Request превышает 4 килобайта
  48. // Нам не нужно получать данные из POST-запроса (и т. п.), а обычный запрос
  49. // по идее не должен быть больше 4 килобайт
  50. if (Request.IndexOf("\r\n\r\n") >= 0 || Request.Length > 4096)
  51. {
  52. break;
  53. }
  54. }
  55. // Парсим строку запроса с использованием регулярных выражений
  56. // При этом отсекаем все переменные GET-запроса
  57. Match ReqMatch = Regex.Match(Request, @"^\w+\s+([^\s\?]+)[^\s]*\s+HTTP/.*|");
  58. // Если запрос не удался
  59. if (ReqMatch == Match.Empty)
  60. {
  61. // Передаем клиенту ошибку 400 - неверный запрос
  62. SendError(Client, 400);
  63. return;
  64. }
  65. // Получаем строку запроса
  66. string RequestUri = ReqMatch.Groups[1].Value;
  67. // Приводим ее к изначальному виду, преобразуя экранированные символы
  68. // Например, "%20" -> " "
  69. RequestUri = Uri.UnescapeDataString(RequestUri);
  70. // Если в строке содержится двоеточие, передадим ошибку 400
  71. // Это нужно для защиты от URL типа [url]http://example.com/file.txt[/url]
  72. if (RequestUri.IndexOf("..") >= 0)
  73. {
  74. SendError(Client, 400);
  75. return;
  76. }
  77. // Если строка запроса оканчивается на "/", то добавим к ней index.html
  78. if (RequestUri.EndsWith("/"))
  79. {
  80. RequestUri += "index.html";
  81. //RequestUri += "index.xml";
  82. }
  83. string FilePath = "www/" + RequestUri;
  84. // Если в папке www не существует данного файла, посылаем ошибку 404
  85. if (!File.Exists(FilePath))
  86. {
  87. SendError(Client, 404);
  88. return;
  89. }
  90. // Получаем расширение файла из строки запроса
  91. string Extension = RequestUri.Substring(RequestUri.LastIndexOf('.'));
  92. // Тип содержимого
  93. string ContentType = "";
  94. // Пытаемся определить тип содержимого по расширению файла
  95. switch (Extension)
  96. {
  97. case ".htm":
  98. case ".html":
  99. ContentType = "text/html";
  100. break;
  101. case ".css":
  102. ContentType = "text/stylesheet";
  103. break;
  104. case ".js":
  105. ContentType = "text/javascript";
  106. break;
  107. case ".jpg":
  108. ContentType = "image/jpeg";
  109. break;
  110. case ".jpeg":
  111. case ".png":
  112. case ".gif":
  113. ContentType = "image/" + Extension.Substring(1);
  114. break;
  115. default:
  116. if (Extension.Length > 1)
  117. {
  118. ContentType = "application/" + Extension.Substring(1);
  119. }
  120. else
  121. {
  122. ContentType = "application/unknown";
  123. }
  124. break;
  125. }
  126. // Открываем файл, страхуясь на случай ошибки
  127. FileStream FS;
  128. try
  129. {
  130. FS = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
  131. }
  132. catch (Exception)
  133. {
  134. // Если случилась ошибка, посылаем клиенту ошибку 500
  135. SendError(Client, 500);
  136. return;
  137. }
  138. // Посылаем заголовки
  139. string Headers = "HTTP/1.1 200 OK\nContent-Type: " + ContentType + "\nContent-Length: " + FS.Length + "\n\n";
  140. byte[] HeadersBuffer = Encoding.ASCII.GetBytes(Headers);
  141. Client.GetStream().Write(HeadersBuffer, 0, HeadersBuffer.Length);
  142. // Пока не достигнут конец файла
  143. while (FS.Position < FS.Length)
  144. {
  145. // Читаем данные из файла
  146. Count = FS.Read(Buffer, 0, Buffer.Length);
  147. // И передаем их клиенту
  148. Client.GetStream().Write(Buffer, 0, Count);
  149. }
  150. // Закроем файл и соединение
  151. FS.Close();
  152. Client.Close();
  153. }
  154. }
  155. class Server
  156. {
  157. TcpListener Listener; // Объект, принимающий TCP-клиентов
  158. // Запуск сервера
  159. public Server(int Port)
  160. {
  161. Listener = new TcpListener(IPAddress.Any, Port); // Создаем "слушателя" для указанного порта
  162. Listener.Start(); // Запускаем его
  163. // В бесконечном цикле
  164. while (true)
  165. {
  166. // Принимаем нового клиента
  167. TcpClient Client = Listener.AcceptTcpClient();
  168. // Создаем поток
  169. Thread Thread = new Thread(new ParameterizedThreadStart(ClientThread));
  170. // И запускаем этот поток, передавая ему принятого клиента
  171. Thread.Start(Client);
  172. }
  173. }
  174. static void ClientThread(Object StateInfo)
  175. {
  176. // Просто создаем новый экземпляр класса Client и передаем ему приведенный к классу TcpClient объект StateInfo
  177. new Client((TcpClient)StateInfo);
  178. }
  179. // Остановка сервера
  180. ~Server()
  181. {
  182. // Если "слушатель" был создан
  183. if (Listener != null)
  184. {
  185. // Остановим его
  186. Listener.Stop();
  187. }
  188. }
  189.  
  190. static void Main(string[] args)
  191. {
  192. // Создадим новый сервер на порту 88
  193. new Server(88);
  194. }
  195. }
  196. }
Вот код моего недо-клиента, который должен получать и обрабатывать ответ сервера. Я слабо представляю, как это должно выглядеть, поэтому просто попытался написать нечто, что будет считывать xml-файл и раскидывать его значения по тектбоксам.
Листинг программы
  1. private void button2_Click(object sender, EventArgs e)
  2. {
  3. var doc = XDocument.Load(@"C:\XMLFile1.xml"); //если запустить так, все отлично парсится
  4. //var doc = XDocument.Load(@"http://127.0.0.1:88/index.xml"); /*а если так, то запускается, но не работает: "The server committed a protocol violation. Section=ResponseStatusLine" */
  5. label3.Text = (doc.Root.Element("incident").Element("category").Attribute("name").Value);
  6. richTextBox1.Text = (doc.Root.Element("incident").Element("description").Value);
  7. richTextBox2.Text = (doc.Root.Element("incident").Element("place").Attribute("x").Value);
  8. richTextBox3.Text = (doc.Root.Element("incident").Element("place").Attribute("y").Value);
  9. richTextBox4.Text = (doc.Root.Element("incident").Element("place").Attribute("street").Value);
  10. richTextBox5.Text = (doc.Root.Element("incident").Element("place").Attribute("numhome").Value);
  11. richTextBox6.Text = (doc.Root.Element("incident").Element("place").Attribute("numflat").Value);
  12. textBox2.Visible = true;
  13. timer1.Enabled = true;
  14. }
По идее, нужно написать что-то вроде:
Листинг программы
  1. private void button1_Click(object sender, EventArgs e)
  2. {
  3.  
  4. try
  5. {
  6. var url = string.Format(@"http://{0}/", textBox1.Text);
  7. System.Net.WebRequest reqGET = System.Net.WebRequest.Create(url);
  8. var resp = reqGET.GetResponse();
  9. System.IO.Stream stream = resp.GetResponseStream();
  10. label5.Text = (new System.IO.StreamReader(stream)).ReadToEnd();
  11. }
  12. catch (WebException ea)
  13. {
  14. //MessageBox.Show("Ошибка");
  15. label1.Text = (ea.GetType().ToString()); //что-то типа лога с ошибками
  16. }
  17. }
вот сам xml:
Листинг программы
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <result>
  3. <incident id="12323">
  4. <category id="12" name="North"/>
  5. <description>
  6. TEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXTTEXT
  7. </description>
  8. <place x="78.34534" y="56.4564566" street="Lenina" numhome="387" numflat="73"/>
  9. </incident>
  10. </result>
Проблема в том, что я не представляю себе, что нужно передать серверу в качестве запроса в GET, и как сервер должен передать XML-код мне обратно, а я считать его. В гугле был, похожие темы видел, но не докурил, не могу понять сам принцип, прошу помощи в общем)

Решение задачи: «Написать простенький веб-сервер и клиент к нему»

textual
Листинг программы
  1. private void button1_Click(object sender, EventArgs e)
  2.         {
  3.             TcpClient tcpClient;
  4.             NetworkStream networkStream;
  5.             StreamReader streamReader;
  6.             StreamWriter streamWriter;
  7.            
  8.             try
  9.             {
  10.                
  11.                 var url = string.Format(@"http://{0}/", textBox1.Text); //считали значение URL из текстбокса
  12.                  System.Net.WebRequest reqGET = System.Net.WebRequest.Create(url); //постали get-запрос на основе URL
  13.                  var resp = reqGET.GetResponse();   // получили ответ
  14.                  System.IO.Stream stream = resp.GetResponseStream(); // ?
  15.                  var nov = new System.IO.StreamReader((stream), Encoding.UTF8);
  16.                  label5.Text = (new System.IO.StreamReader(stream)).ReadToEnd(); // сюда по идее должна вставлять та самая передаваемая строчка, однако catch подхватывает ошибку и ничего не происходит
  17.                  
  18.             }
  19.  
  20.             catch (WebException ea)
  21.             {
  22.               label1.Text = (ea.GetType().ToString());
  23.             }
  24.  
  25.           }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

8   голосов , оценка 4.625 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы