Я создал сервер с TcpListener, который отвечает на каждый запрос как фиктивный HTTP.На стороне клиента я использовал jQuery Ajax, чтобы сделать запрос к этому серверу.Сервер получает успешный запрос и отвечает на него.
Проблема в том, что если я делаю запрос в браузере, набирая адрес, он работает, и я вижу результат.Если я пытаюсь сделать запрос jQuery.ajax (...), ajax завершается ошибкой.Если я использую Chrome inspector для мониторинга сети, я вижу, что он не получает даже ответ от сервера.Почему это так?
Моя миссия намного больше, чем этот код, которым я поделюсь с вами.Но он ведет себя так же.
.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?
Edit # 1
Я отлаживал DummyServer, и ajax получает ошибку в тот момент, когда я начинаю писать в поток.Даже если я установлю параметр тайм-аута на ajax-запрос и пошагово отлажу его, на этом же шаге (на поток) я получаю ошибку.
Edit # 2
Когда я пишу HTTPЗаголовки и данные отдельно, а затем 2 байта от конца данных теряются после передачи.
Если я напишу весь Dummy 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, используйте Proxy, как показано ниже.
Как вы могли прочитать, существует проблема политики между различными портами и доменами.Лучший способ решить эту проблему - установить прокси-сервер в свой домен и порт.Я сделал мой с 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'];
?>