http-сервер программа на вашем хост-комп. закрыла соединение - где лишнее закрытие?
#39616236
Ссылка:
Ссылка на сообщение:
Ссылка с названием темы:
Ссылка на профиль пользователя:
|
Участник
Откуда: Брянск
Сообщения: 269
|
|
Добрый день.
Есть задача - рассмотреть написание простейшего http-сервера для примера.
HttpServer
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39.
using System.Net;
using System.Net.Sockets;
namespace http_server
{
// Http-сервер
public class HttpServer
{
private TcpListener tcp_listener1;
public HttpServer(int port)
{
tcp_listener1 = new TcpListener(IPAddress.Any, port);
tcp_listener1.Start(); // Ожидание соединений по указанному порту
while (true)
{
new HttpClient(tcp_listener1.AcceptTcpClient());
//TcpClient client = tcp_listener1.AcceptTcpClient(); // Принимаем клиентов
//System.Threading.Thread t1 = new System.Threading.Thread(ClientProcessing);
//t1.Start(client);
}
}
void ClientProcessing(object client)
{
new HttpClient((TcpClient)client);
}
~HttpServer()
{
if (tcp_listener1 != null) tcp_listener1.Stop(); // Остановка прослушивания
}
}
}
HttpClient
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144.
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
namespace http_server
{
public class HttpClient
{
public HttpClient(TcpClient Client)
{
string Request = ""; // Запрос клиента
byte[] Buffer = new byte[4096]; // Буфер для хранения принятых от клиента данных
int Count; // Кол-во байт, приянтых от клиента
// Читаем из потока клиента до тех пор, пока от него поступают данные
while ((Count = Client.GetStream().Read(Buffer, 0, Buffer.Length)) > 0)
{
Request += System.Text.Encoding.ASCII.GetString(Buffer, 0, Count);
if (Request.Length > 4096) return;
}
// Обработка строки запроса - убираем параметры в запросе
Match ReqMatch = Regex.Match(Request, @"^\w+\s+([^\s\?]+)[^\s]*\s+HTTP/.*|");
if (ReqMatch == Match.Empty) // Если запрос не удался
{
SendError(Client, 400); // Передаем клиенту ошибку 400 - неверный запрос
return;
}
string RequestUri = ReqMatch.Groups[1].Value; // Получаем строку запроса
RequestUri = System.Uri.UnescapeDataString(RequestUri); // Преобразование кодированных символов к изначальному виду
// Если в строке содержится двоеточие, передадим ошибку 400
// Это нужно для защиты от URL типа http://example.com/../../file.txt
if (RequestUri.IndexOf("..") >= 0)
{
SendError(Client, 400);
return;
}
// Если строка запроса оканчивается на "/", то добавим к ней index.html
if (RequestUri.EndsWith("/"))
{
RequestUri += "index.html";
}
// Этап - возвращение клиенту запрашиваемого контента
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 (System.Exception)
{
// Если случилась ошибка, посылаем клиенту ошибку 500
SendError(Client, 500);
return;
}
// Посылаем заголовки
string Headers = "HTTP/1.1 200 OK\nContent-Type: " + ContentType + "\nContent-Length: " + FS.Length + "\n\n";
byte[] HeadersBuffer = System.Text.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();
}
// Возврат клиенту ошибки
private void SendError(TcpClient Client, int Code)
{
string CodeStr = Code.ToString() + " " + ((HttpStatusCode)Code).ToString(); // Получаем строку с кодом ошибки
string Html = "<html><body><h1>" + CodeStr + "</h1></body></html>"; // Формируем html-страницу с кодом ошибки
string Str = "HTTP/1.1 " + CodeStr + "\nContent-type: text/html\nContent-Length:" + Html.Length.ToString() + "\n\n" + Html; // Заголовки и содержимое страницы
byte[] Buffer = System.Text.Encoding.ASCII.GetBytes(Str);
Client.GetStream().Write(Buffer, 0, Buffer.Length); // Отправка клиенту результата
Client.Close(); // Закрываем соединение
}
}
}
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
Program.cs:
namespace http_server
{
class Program
{
static void Main(string[] args)
{
HttpServer http_server_1 = new HttpServer(80); // Запуск http-сервера на порту 80
}
}
}
Судя по всему, где-то преждевременно закрывается соединение.
Однако-где?
|
|