2

I've got a working HTTP node.js server.

I then created a program on python that uses the socket module to connect to the above server

Please for the time being do not mind the try and except statements. The code's connectTO() function simply connects to a server like any other code, with the exception that it handles some errors. Then the program send the message "hello". Next in the while loop it repeatedly waits for an answer and when it receives one, it prints it.

When I connect to the Node.js http server from python, I do get the message:

"You have just succesfully connected to the node.js server"

Which if you look at my code means that the s.connect(()) command was successful. My problem is that when a request is send to the server, it's supposed to output a message back, but it doesn't.

I also tried sending a message to the server, in which case the server sends back the following message:

HTTP/1.1 400 Bad Request

So why is the server not responding to the requests? Why is it rejecting them?

Python Client:

from socket import AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
import threading, socket, time, sys

s = socket.socket(AF_INET,SOCK_STREAM)

def connectTO(host,port):
    connect = False
    count = 0
    totalCount = 0
    while connect!= True:
        try:
            s.connect((host,port))
            connect = True
            print("You have just succesfully connected to the node.js server")
        except OSError:
            count += 1
            totalCount += 1
            if totalCount == 40 and count == 4:
                print("Error: 404. Connection failed repeatedly")
                sys.exit(0)
            elif count == 4:
                print("Connection failed, retrying...")
                count = 0
            else:
                pass          

connectTO("IP_OF_NODE.jS_SERVER_GOES_HERE",777)
message = "hello"
s.send(message.encode("utf-8"))

while True:
    try:
        data, addr = s.recvfrom(1024)
        if data == "":
            pass
        else:
            print(data.decode())
    except ConnectionResetError:
        print("it seems like we can't reach the server anymore..")
        print("This could be due to a change in your internet connection or the server.")
    s.close()

Node.js HTTP server:

function onRequest(req, res) {
    var postData = "";
    var pathname = url.parse(req.url).pathname;

    //Inform console of event recievent
    console.log("Request for "+pathanme+" received.");

    //Set the encoding to equivelant one used in html
    req.setEncoding("utf8");

    //add a listener for whenever info comes in and output full result
    req.addListener("data", function(postDataChunk) {
        postData += postDataChunk;
        console.log("Received POST data chunk: '"+postDataChunk+"'");
    });

    req.addListener("end", function() {
        route(handle, pathname, res, frontPage, postData);
    });

};

http.createServer(onRequest).listen(port,ip);
console.log("Server has started.");

Some of my Research

I should also note that after some research, it seems that an HTTP server accepts HTTP requests, but I don't understand most of what's on Wikipedia. Is this the reason why the server is not responding? And how do I fix that while still using the socket module.

Also there are a lot of similar questions on Stack Overflow, but none help me solve my problem. One of them describes my issue, and the only answer is about "handshakes". Google is also pointless here, but from what I understand it is simply a reaction between the server and the client which defines what the protocol will be. Could this be what I'm missing, and how do I implement it?

Some of these questions also use modules that I'm not ready to use yet like websocket. Either that or they describe a way in which the server connects to the client, which can be done by directly calling python code or connecting to it from Node.js express. I want the client to be the one connecting to an HTTP server, by the means of the socket module in python. For the sake of future visitors who are looking for something like this, here are some of these question:


Here is an answer that doesn't actually seem that obvious, but also solves the issue with only the relevant code. People who don't yet no much about servers in general will have probably missed it: how to use socket fetch webpage use python

  • 1
    The server IS responding. HTTP only accepts HTTP requests. You're connecting over TCP so you will need to construct one. – Eli Richardson Dec 09 '17 at 18:20
  • You need an HTTP client library. Playing with low leve socket like this is not enough. Try your server with `curl, `wget` or a browser. Then, if successful, use a high level HTTP module for Python like `urllib.request` from stdlib or the - excellent - 3rd party packege `requests`. – glenfant Dec 09 '17 at 18:25
  • 1
    Possible duplicate of [how to use socket fetch webpage use python](https://stackoverflow.com/questions/14140914/how-to-use-socket-fetch-webpage-use-python). That should explain everything you need to do! – Robert Moskal Dec 09 '17 at 18:29
  • @Robert Moskal yes I have read this question and it is valid. However the _how_ it works is something very important to me. I don't like hacking things up without actually understanding them. The link below makes it clear what is happening exactly and why. Moreover the question you linked to isn't something I came across when searching on google and SO, while this one is more specific about the actual problems. Other people who have similar problems like me who don't know much about HTTP and node.js wouldn't realize that this questions solves their problem, while this makes it clear. –  Dec 09 '17 at 18:36
  • For a more relevant code (the answer has code that is relevant only to my program) look at : https://stackoverflow.com/questions/14140914/how-to-use-socket-fetch-webpage-use-python it is not blatantly obvious to solve the issue but it is the same valid answer as the one below. –  Dec 09 '17 at 18:54

1 Answers1

2

You will need to construct an HTTP request.

Example: GET / HTTP/1.1\n\n

Try this:

from socket import AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
import threading, socket, time, sys

s = socket.socket(AF_INET,SOCK_STREAM)

def connectTO(host,port):
    connect = False
    count = 0
    totalCount = 0
    while connect!= True:
        try:
            s.connect((host,port))
            connect = True
            print("You have just succesfully connected to the node.js server")
        except OSError:
            count += 1
            totalCount += 1
            if totalCount == 40 and count == 4:
                print("Error: 404. Connection failed repeatedly")
                sys.exit(0)
            elif count == 4:
                print("Connection failed, retrying...")
                count = 0
            else:
                pass          

connectTO("IP_OF_NODE.jS_SERVER_GOES_HERE",777)
message = "GET / HTTP/1.1\n\n"
s.send(message.encode("utf-8"))

while True:
    try:
        data, addr = s.recvfrom(1024)
        if data == "":
            pass
        else:
            print(data.decode())
    except ConnectionResetError:
        print("it seems like we can't reach the server anymore..")
        print("This could be due to a change in your internet connection or the server.")
    s.close()

Read this to learn more about HTTP.

Now, I would recommend using this python lib to do what you're trying to do. It makes things much easier. However, if you are 100% set on using raw sockets, then you should make the node server use raw sockets as well. (Assuming you will only be connecting via python). Here is an excellent tutorial

Eli Richardson
  • 934
  • 7
  • 25
  • Here is a big thanks, an upvote (although I can't upvote yet), and an accept for a very helpful answer. You solved my problem and the link pretty much tells me what I needed to understand about this –  Dec 09 '17 at 18:32