简体   繁体   中英

How to read HTTP response with jQuery ajax from C# TcpListener?

I have created server with TcpListener, which responds to every request as a dummy HTTP. On the client side I have used jQuery Ajax to make a request to this server. Server gets successul request and responds to it.

Problem is if I make a request with browser by typing address, it works and I can see the result. If I try to make jQuery.ajax(...) request then ajax fails with an error. If I use Chrome inspector to monitor network I see it doesn't get even a response from the server. Why is this so?

My mission is way bigger than this code I will share with you. But it behaves the same.

.NET C# @ Server side:

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 and jQuery Ajax @ Client side:

<!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>

What am I doing wrong? Browser understands this response because its made to parse html from everykind of s*it?

Edit #1

I debugged DummyServer and ajax gets error at the time I start to write to the stream. Even if I set timeout parameter to ajax request and debug it step-by-step it gives me error in the same step (witing to stream).

Edit #2

When I write HTTP Headers and data separately then 2 bytes from the end of the data ar getting lost after the transmission.

If I write whole Dummy HTTP at once, then they don't get lost. It seems like NetworkStream.Write method writes extra \\r\\n after the data I provide to it.

// 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();

Browser will show 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();

Browser will show 12345678

If NetworkStream.Write method writes extra \\r\\n to after my written bytes then couldn't this be the problem?

Solution

You could just use jsonp with GET. jQuery.getJSON(url, callback);

If you need POST, then use Proxy like as follows.

As you could read there is an policy issue between different ports and domains. The best way to solve it is to put somekind of Proxy into your domain&port. I did mine with php.

My communication is done with JSON. At both ends with my own defined structure. So I am just forwarding my request to host and back to client. I just have to set enough big timeout for 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'];
?>

According to these additional notes here: http://api.jquery.com/jQuery.get/#notes-0

Due to browser security restrictions, most "Ajax" requests are subject to the same origin policy ; the request can not successfully retrieve data from a different domain, subdomain, or protocol.

You might find this question also useful: jQuery POST to a .NET HttpListener and back again

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM