Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I want to connect my laptop (and later a raspberry pi/Jetson nano) to a Server. The goal is to be able to send data to the server then process and evaluate it and send the output (GPS coordinates) back to the client (laptop/raspberry pi/Jetson nano).
Ideally, I would just plug in the public IP address of the Google Server into the code that is run on the client and connect to the server.
However, running the server code:
import socket
HOST = '127.0.0.1' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
and the client code:
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))
provided by: https://realpython.com/python-sockets/ .
Will only work with the default local IP address otherwise it returns a IP address couldn't be found error.
EDIT: The answer was more directed towards internet connection via the google cloud API. The solution illustrates this perfectly, however my question was not explicit enough sorry!
There's a large number of ways to do this, but I would recommend using either a GCE instance as your server, or an App Engine deployment. Cloud Run and Cloud Functions also would work. (EDIT: forgot k8s)
Note that when using a GCE instance you will need to open up your firewall as per documentation.
Also note that unless you assign a static IP address to the GCE instance, it will be ephemeral. If you use App Engine, you can just use https://project-id.appspot.com/ as the server address in your client.
You'll need to set up a simple web server using Flask, FastAPI or another webapp framework. It makes life easier to use a simple framework as it will take load of your hands.
You can have your client perform a request with the data it needs to send as parameters and have the web app perform magic and provide a response. I would highly advise to return a JSON response as this is more or less standard for APIs. (which your web app would basically be). Also, as you might know, JSON is easily converted into something useable in python.
See this very simple example below.
server code
from flask import Flask, request
import json
app = Flask(__name__)
longitude_divisor = 0.004167
#app.route("/api/gettimediff")
def gettimediff():
longitude = float(request.args.get("Longitude"))
# http://www.cs4fn.org/mobile/owntimezone.php
seconds = longitude / longitude_divisor
response = json.dumps({"seconds": seconds}, indent=4)
return response
#app.route("/api/switch")
def switch():
longitude = float(request.args.get("Longitude"))
latitude = float(request.args.get("Latitude"))
response = json.dumps({"Latitude": longitude, "Longitude": latitude})
return response
if __name__ == "__main__":
# This is used when running locally only. When deploying to Google App
# Engine, a webserver process such as Gunicorn will serve the app. This
# can be configured by adding an `entrypoint` to app.yaml.
# Flask's development server will automatically serve static files in
# the "static" directory. See:
# http://flask.pocoo.org/docs/1.0/quickstart/#static-files. Once deployed,
# App Engine itself will serve those files as configured in app.yaml.
app.run(host="127.0.0.1", port=8080, debug=True)
client code
import requests
import json
serveraddress = "http://127.0.0.1:8080/"
data = {"Latitude": 48.85837, "Longitude": 2.294481}
print("switch")
response = requests.get(
f"{serveraddress}api/switch",
params=data
)
print(data)
print(response.text)
print("seconds")
response = requests.get(
f"{serveraddress}api/gettimediff",
params=data
)
print(data)
print(response.text)
converted = json.loads(response.text)
print(converted)
Related
I am writing a Python script that interacts with the Spotify API. To authenticate, I generate a url that looks something like this: https://accounts.spotify.com/authorize?response_type=token&client_id=<client_id_here>&redirect_uri=http%3A%2F%2F127.0.0.1%3A8083. Spotify then redirects me to my redirect uri, which is currently localhost (127.0.0.1:8083). Spotify attaches the access token as a fragment to the redirect uri. I need to access the uri fragment from Python.
Currently I am using the following code (the function generate_login_url() generates the accounts.spotify.com url I need)
webbrowser.open(generate_login_url())
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind(('127.0.0.1', 8083))
sock.listen()
conn, _ = sock.accept()
with conn:
data = conn.recv(1024)
conn.sendall(data)
When I run this, I can see in the web browser that I have been redirected to the correct url (http://127.0.0.1:8083/#access_token=<access_token_here>&token_type=Bearer&expires_in=3600) but I cannot find a way to access the fragment from python. Calling conn.recv(1024) again causes a timeout, and the information I need is not found anywhere in data, which seems to just hold the user-agent string and the headers.
*Before you mark as duplicate please note that I am referencing this similar question found here:
Python Socket Programming - ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
unfortunately but have found anything in that post that provides a solution to my problem.
I am working on a very basic exercise designed to familiarize students with programming related to networks. This particular assignment is a common one as is described as follows:
In this assignment, you will learn the basics of socket programming for TCP connections in Python: how to create a socket, bind it to a specific address and port, as well as send and receive an HTTP packet. You will also learn some basics of HTTP header format. You can only use Python3.
You will develop a web server that handles one HTTP request at a time. Your web server should accept and parse the HTTP request, get the requested file from the server’s file system, create an HTTP response message consisting of the requested file preceded by header lines, and then send the response directly to the client. If the requested file is not present in the server, the server should send an HTTP “404 Not Found” message back to the client.
Part one specification:
Put the attached HTML file (named HelloWorld.html) in the same directory in which the server webserver.py runs. Run the server program. Determine the IP address of the host that is running the server (e.g., 128.238.251.26 or localhost). From another host, open a browser and provide the corresponding URL. For example: http://128.238.251.26:6789/HelloWorld.html. You can open a browser in the same host where the server runs and use the following http://localhost:6789/HelloWorld.html.
‘HelloWorld.html’ is the name of the file you placed in the server directory. Note also the use of the port number after the colon. You need to replace this port number with the port number that was assigned to you. In the above example, we have used port number 6789. The browser should then display the contents of HelloWorld.html. If you omit “:6789”, the browser will assume port 80 (why?), and you will get the web page from the server only if your server is listening at port 80.
Then try to get a file that is not present on the server (e.g., test.html). You should get a “404 File Not Found” message.
Part Two specification:
Write your own HTTP client to test your server. Your client will connect to the server using a TCP connection, send an HTTP request to the server, and display the server response as an output. You can assume that the HTTP request sent is a GET method. The client should take command line arguments specifying the server IP address or hostname, the port at which the server is listening, and the HTTP file name (e.g., test.html or HelloWorld.html). The following is an input command format to run the client. webclient.py <server_host> <server_port>
My code is for the Webserver is as follows:
#import socket module
from socket import *
import sys # In order to terminate the program
serverSocket = socket(AF_INET, SOCK_STREAM)
# Prepare a sever socket
# Fill in start
serverHost = '192.168.1.4'
serverPort = 56014
serverSocket.bind((serverHost, serverPort))
serverSocket.listen(5)
# Fill in end
while True:
#establish connection
print('The server is ready to receive')
connectionSocket, addr = serverSocket.accept() # Fill in start #Fill in end
try:
message = connectionSocket.recv(4096) # Fill in start #Fill in end
filename = message.split()[1]
f = open(filename[1:])
outputdata = f.readlines() # Fill in start #Fill in end
# send one http header line in to the socket
# Fill in start
connectionSocket.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n")
connectionSocket.send("\r\n")
# Fill in end
# Send the content of the requested file to the connection socket
for i in range(0, len(outputdata)):
connectionSocket.send(outputdata[i].encode())
connectionSocket.send("\r\n".encode())
connectionSocket.close()
except IOError:
# Send HTTP response code and message for file not found
# Fill in start
connectionSocket.send("HTTP/1.1 404 Not Found\r\n")
connectionSocket.send("Content-Type: text/html\r\n")
connectionSocket.send("\r\n")
connectionSocket.send("<html><head></head><body><h1>404 Not Found</h1></body></html><\r\n>")
# Fill in end
# Close the client connection socket
# Fill in start
serverSocket.close()
# Fill in end
serverSocket.close()
sys.exit() # Terminate the program after sending the corresponding data
My code for the Webclient is as follows:
from socket import *
import sys
serverName = sys.argv[1]
serverPort = int(sys.argv[2])
fileName = sys.argv[3]
request = "GET "+str(fileName)+" HTTP/1.1"
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
clientSocket.send(request.encode())
returnFromSever = clientSocket.recv(4096)
while(len(returnFromSever)>0):
print(returnFromSever.decode())
returnFromSever = clientSocket.recv(4096)
clientSocket.close()
The error I am receiving is:
"No connection could be made because the target machine actively refused it"
Admittedly, I know almost nothing about network related programming and on top of that I am not familiar with the Python syntax (my entire degree program was exclusively in Java) so I am very lost here and somewhat desperate.
If anyone could please point me in the right direction as far as how to correct this error, I would be very deeply grateful.
Thanks
The error you are getting (No connection could be made because the target machine actively refused it) means that the port you are trying to connect to is not not being listened on the server.
For example, if you try to connect to 192.168.1.1:80 (IP = 192.168.1.1, port=80) and the server on 192.168.1.1 doesn't listen on port 80, you would receive this error.
A few things I would check in your case:
Is your server IP actually 192.168.1.4 ? If not, set it to the correct IP of the interface you want to listen on. If you want to listen on all the interfaces of the server, use this: serverHost = '0.0.0.0'
Does your client code attempt to connect to the server port? The server port is 56014. You need to pass it as the second parameter of your client program (because of this line serverPort = int(sys.argv[2])).
I want to create streaming videos by using a socket. I need to know how I can find the port number address.
My code that I wrote to create a client:
# create socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host_ip = '192.168.0.165' # paste your server ip address here
port =
client_socket.connect((host_ip, port)) # a tuple
data = b""
payload_size = struct.calcsize("Q") # Q: unsigned long long integer(8 bytes)
Can you post the code from your service app? (or name the service app) Usually you declare the port in the service somewhere. If its prebuilt, it could be in a configuration file.
You can run cmd.exe and type netstat to check your port activity. Or go to your firewalls inbound/outbound rules. Typically if its a prebuilt app it will create a firewall rule with associated port so the firewall does not freak out when connections come in to that port.
But otherwise there is not enough information here for me to give a complete answer.
I am trying to learn how to use sockets to send files between pcs on my local network.
I am using ubuntu on my 'server' and my original plan was to create a ufw rule that allows all LAN connections but ask for a password when accepting the socket connection. That way only devices that are really supposed to communicate with the server would be accepted.
I do realise that creating ufw rules for static IPs would be an option but unfortunately I am dealing with dynamic IPs.
I have a text file of allowed keys on my 'server' and a text file containing one authentication key on the 'client'.
The server script looks like this:
#!/usr/bin/env python3
import socket
with open('/path/to/allowedKeys') as f:
allowedKeys = []
for line in f:
allowedKeys.append(line.rstrip('\n'))
HOST = '127.0.0.1' #standard loopback interface address (localhost)
PORT = 9999
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((HOST, PORT))
serversocket.listen()
(clientsocket, address) = serversocket.accept()
with clientsocket:
print('Connected by', address)
while True:
data = clientsocket.recv(1024)
data = data.decode(encoding="utf-8")
print('Received', repr(data))
if data in allowedKeys:
clientsocket.sendall(b'Thank you for logging in.')
clientsocket.shutdown(socket.SHUT_RDWR)
break
else:
clientsocket.sendall(b'Error: Failed authentication')
clientsocket.shutdown(socket.SHUT_RDWR)
break
and the client script looks like this:
#!/usr/bin/env python3
import socket
with open('/path/to/authenticationKey', 'r') as f: #read authenticationKey from textfile
authenticationKey = f.readline().rstrip('\n')
authenticationKey = bytes(authenticationKey, encoding="utf-8") #convert authenticationKey to bytes
#authenticationKey = bytes('wrongKey', encoding="utf-8") #wrong Key for testing
HOST = '127.0.0.1' #server hostname or IP address
PORT = 9999 #port used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(authenticationKey)
data = s.recv(1024)
s.shutdown(socket.SHUT_RDWR)
s.close()
print('Received', repr(data))
When I execute the scripts it looks like everything works as expected.
I get either
Received 'nhjp9NIin987BUHBlkuULK98zJKn98JH'
or
Received 'wrongKey'
and the server shuts down successfully.
I have looked at these two related questions:
socket accept only specific addresses?
Server socket - accept connections only from IP addresses in the whitelist
While I cannot filter by IP it seems as if one must first accept the connection in order to authenticate the client.
I only want devices that possess an allowed key to be able to communicate with the server. All other connections should be shut down.
Since I still have very limited knowledge I would like to know whether this is the way to go or whether this leaves me open to any vulnerabilities.
While I cannot filter by IP it seems as if one must first accept the connection in order to authenticate the client. I only want devices that possess an allowed key ..
Since you want to authenticate a client based on actual data (the key or proof of possession of the key) then you must first have a connection able to transfer the data from the client. With TCP this means that you have to accept the connection.
... whether this leaves me open to any vulnerabilities.
This is the usual way to go but it leaves you open to denial of service attacks. Creating a new connection takes resources, so by opening lots of connections an attacker can exhaust server resources. If all resources are exhausted this way even valid users can no longer access the server. See for example the SYN flood attack.
Depending on the setup of the client additional protections can be added. But these are outside of the python application and mostly out of scope of this question. But to get some ideas see the section about countermeasures in the Wikipedia article.
My port forward rule
I've created a python TCP server and client which is working fine when I launch both server and client on my computer and when I launch the server and the client on different computers on the same network, however I wanted to make it work when computers are in different networks. I have forwarded my router port 8080 to convert to 8888 in my computer, in fact I have also a rule for the port 80 on my router converting to 8080 on my PC which is the Wamp server, and as the python server is not working I guessed it was from the code but I can't figure it out:
Server:
import socket
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.bind(("127.0.0.1", 8888))
sck.listen(1)
conn, adr = sck.accept()
print('Connected to ', adr)
while 1:
data = conn.recv(1024).decode()
if data and ('over' not in data):
conn.send(data.encode())
continue
break
conn.close()
Client:
import socket
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect(('<my_external_ip>', 8888))
while True:
data = input('Say something: ')
if 'Shut up' in data:
sck.send('over'.encode())
sck.close
break
sck.send(data.encode())
I've made this test:
Started Wamp server and tried to access it by my external ip with chrome (working)
Opened my Python TCP Client and connected to the Wamp server (working)
Turned Wamp off and started my python server with the same port as Wamp, then tried to acess with the python client (not working)
If there's nothing wrong with the TCP Server code why does Wamp work and he don't? Please check the following - Whats the logic behind binding 127.0.0.1 I couldn't understand... Won't that make it only be accessible by my PC?
If that part is ok than at least is something related to the Server code I guess...