如何使用C#TcpListener中的jQuery ajax读取HTTP响应?

vel*_*tis 5 c# ajax tcplistener httpresponse httprequest

我用TcpListener创建了服务器,它将每个请求作为虚拟HTTP响应.在客户端,我使用jQuery Ajax向该服务器发出请求.服务器获得成功请求并响应它.

问题是如果我通过输入地址向浏览器发出请求,它可以工作,我可以看到结果.如果我尝试发出jQuery.ajax(...)请求,那么ajax会因错误而失败.如果我使用Chrome检查器来监控网络,我发现它甚至无法从服务器获得响应.为什么会这样?

我的任务比我将与你分享的代码更大.但它的行为相同.

.NET C#@ Server端:

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();
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

HTML和jQuery Ajax @ Client端:

<!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>
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?浏览器理解这个响应,因为它是从每个s*解析html的吗?

编辑#1

我调试了DummyServer,当我开始写入流时,ajax会收到错误.即使我将timeout参数设置为ajax请求并逐步调试它,它也会在同一步骤中给出错误(witing to stream).

编辑#2

当我单独写HTTP Headers和数据时,数据末尾的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();
Run Code Online (Sandbox Code Playgroud)

浏览器将显示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();
Run Code Online (Sandbox Code Playgroud)

浏览器将显示12345678

如果NetworkStream.Write方法在写入的字节之后将额外的\ r \n写入,那么这不是问题吗?

你可以在jET中使用jsonp.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'];
?>
Run Code Online (Sandbox Code Playgroud)

hs2*_*s2d 3

根据此处的这些附加注释: http: //api.jquery.com/jQuery.get/#notes-0

由于浏览器安全限制,大多数“Ajax”请求都受到同源策略的约束;该请求无法成功检索来自不同域、子域或协议的数据。

您可能会发现这个问题也很有用:jQuery POST to a .NET HttpListener and back Again