Я создал сервер с TcpListener, который отвечает на каждый запрос как фиктивный HTTP. На стороне клиента я использовал jQuery Ajax, чтобы сделать запрос к этому серверу. Сервер получает успешный запрос и отвечает на него.
Проблема в том, что если я делаю запрос в браузере, набирая адрес, он работает, и я вижу результат. Если я попытаюсь сделать запрос jQuery.ajax (...), тогда ajax завершится с ошибкой. Если я использую инспектор Chrome для мониторинга сети, я вижу, что он не получает даже ответа от сервера. Почему это так?
Моя миссия намного больше, чем этот код, которым я поделюсь с вами. Но ведет себя так же.
.NET C # @ на стороне сервера:
using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace Server {
public class Server
{
public static void Main()
{
try
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234);
tcpListener.Start();
while (true)
{
Socket socket = tcpListener.AcceptSocket();
DummyServer server = new DummyServer(socket);
Thread thrd = new Thread(new ThreadStart(server.Run));
thrd.Start();
}
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
public class DummyServer
{
public DummyServer(Socket socket)
{
_socket = socket;
}
Socket _socket;
public void Run()
{
try
{
// Get stream
var networkStream = new NetworkStream(_socket);
// Read from stream and decode to string
byte[] reqBuffer = new byte[32768];
int read = networkStream.Read(reqBuffer, 0, reqBuffer.Length);
string requestString = Encoding.UTF8.GetString(reqBuffer , 0, read);
Console.WriteLine(requestString);
Console.WriteLine();
// Dummy response HTTP
String responseString =
"HTTP/1.1 200 OK\r\n" +
"Content-Type: application/json\r\n" +
"Content-Length: 15\r\n" +
"\r\n" +
"{\"test\":\"test\"}";
Console.WriteLine(responseString);
Console.WriteLine();
// Write response
byte[] respBuffer = Encoding.UTF8.GetBytes(responseString);
networkStream.Write(respBuffer, 0, respBuffer.Length);
networkStream.Close();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
Console.WriteLine(e.Message);
}
finally
{
// Disconnect and close the socket.
if (_socket != null)
{
if (_socket.Connected)
{
_socket.Close();
}
}
}
}
}
}
HTML и jQuery Ajax @ на стороне клиента:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
jQuery.ajax({
url: 'http://localhost:1234',
type: 'POST',
data: JSON.stringify({test: "test"}),
dataType: 'text',
success: function(result) {
$("body").append("nice<br />");
},
error: function(a, b, c) {
$("body").append("damn<br />");
}
});
$("body").append("done<br />");
});
</script>
</head>
<body>
</body>
</html>
Что я делаю не так? Браузер понимает этот ответ, потому что он предназначен для синтаксического анализа html из любого вида s * it?
Я отлаживал DummyServer, и ajax выдает ошибку в то время, когда я начинаю писать в поток. Даже если я установил параметр тайм-аута для запроса ajax и отлаживаю его шаг за шагом, он дает мне ошибку на том же этапе (ожидание потоковой передачи).
Когда я пишу заголовки HTTP и данные отдельно, то 2 байта с конца данных теряются после передачи.
Если я напишу весь фиктивный HTTP сразу, они не потеряются. Похоже, что метод NetworkStream.Write записывает дополнительный \ r \ n после данных, которые я ему предоставляю.
// Dummy response HTTP Headers
String responseHeader =
"HTTP/1.1 200 OK\r\n" +
"Content-Type: application/json\r\n" +
"Content-Length: 8\r\n" +
"\r\n"
// Dummy response data
String responseData =
"12345678";
//Write header
byte[] respBuffer = Encoding.UTF8.GetBytes(responseHeader );
networkStream.Write(respBuffer, 0, respBuffer.Length);
//Write data
respBuffer = Encoding.UTF8.GetBytes(responseData );
networkStream.Write(respBuffer, 0, respBuffer.Length);
networkStream.Close();
Браузер покажет 123456
// Dummy response HTTP
String responseString =
"HTTP/1.1 200 OK\r\n" +
"Content-Type: application/json\r\n" +
"Content-Length: 8\r\n" +
"\r\n" +
"12345678";
//Write Dummy HTTP
byte[] respBuffer = Encoding.UTF8.GetBytes(responseHeader );
networkStream.Write(respBuffer, 0, respBuffer.Length);
networkStream.Close();
Браузер покажет 12345678
Если метод NetworkStream.Write записывает лишние \ r \ n после моих записанных байтов, то не может ли это быть проблемой?
Вы можно просто использовать jsonp с GET. jQuery.getJSON (url, callback);
Если вам нужен POST, используйте прокси, как показано ниже.
Как вы могли прочитать, существует проблема политики между разными портами и доменами. Лучший способ решить эту проблему - установить какой-нибудь прокси в свой домен и порт. Я сделал свой с помощью php.
Мое общение осуществляется с помощью JSON. На обоих концах моя собственная определенная структура. Итак, я просто пересылаю свой запрос на хост и обратно клиенту. Мне просто нужно установить достаточно большой тайм-аут для ajax.
<?php
function post_request($data, $referer='') {
$host = "localhost";
$port = 7777;
$fp = fsockopen($host, $port, $errno, $errstr, 5);
if ($fp){
// send the request headers:
fputs($fp, "POST / HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
if ($referer != '')
fputs($fp, "Referer: $referer\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ". strlen($data) ."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $data);
$result = '';
while(!feof($fp)) {
// receive the results of the request
$result .= fgets($fp, 128);
}
}
else {
return array(
'status' => 'err',
'error' => "$errstr ($errno)"
);
}
// close the socket connection:
fclose($fp);
// split the result header from the content
$result = explode("\r\n\r\n", $result, 2);
$header = isset($result[0]) ? $result[0] : '';
$content = isset($result[1]) ? $result[1] : '';
// return as structured array:
return array(
'status' => 'ok',
'header' => $header,
'content' => $content
);
}
$req = post_request($_POST['data']); // on jQuery ajax side data must be "data: 'data='+JSON.stringify({test: "test"}),
header("Content-Type: application/json");
echo $req['content'];
?>