I'm trying use the python socket module to connect to an ngrok server. If I put the ngrok into my browser it connects properly so the problem is somewhere with my client code. Here is the server code:
#server.py
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
if __name__ == "__main__":
HOST, PORT = "192.168.86.43", 8080
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
And here is the client:
#client.py
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect(("http://urlhere.ngrok.io", 8080))
sock.sendall(bytes("Hello" + "\n", "utf-8"))
Thanks!
In general you should be able to connect to any globally available address or DNS name, ensuring there is no network restrictions on the way. However you have to listen on the address that is locally available for global routing if you are communicating across the Internet.
As for particular code, there are 2 issues:
Socket should be connected to an address or DNS name. The protocol is defined with the socket type. In your case
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect(("localhost", 8080))
sock.sendall(bytes("Hello" + "\n", "utf-8"))
You're binding in the server to some speciffic not related address. To run your code you should bind to either localhost or to "any available" address "0.0.0.0":
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 8080
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Related
I'm trying to setup a threaded server where multiple clients can connect at the same time. This is a bit long, please do bear with me. I've already read this helpful realpython article on sockets as well as the socket and socketserver docs.
Python provides facilities to create a server and the socketserver documentation even shows us:
import socket
import threading
import socketserver
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def client(ip, port, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((ip, port))
sock.sendall(bytes(message, 'ascii'))
response = str(sock.recv(1024), 'ascii')
print("Received: {}".format(response))
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "localhost", 0
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
with server:
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.daemon = True
server_thread.start()
print("Server loop running in thread:", server_thread.name)
client(ip, port, "Hello World 1")
client(ip, port, "Hello World 2")
client(ip, port, "Hello World 3")
server.shutdown()
This works fine on my machine but what I'd like to de-couple the client implementation from the server. So I split the implementations and I have.
server.py:
import socketserver
import threading
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def main():
HOST, PORT = "localhost", 8080 # localhost aka 127.0.0.1
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
with server:
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = False # Do not stop and keep serving
server_thread.start()
print("Server loop running in thread: ", server_thread.name)
if __name__ == '__main__':
main()
and client.py
import socket
class Client:
def __init__(self, ip, port):
self.ip = ip
self.port = port
def start(self, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((self.ip, self.port))
sock.sendall(bytes(message, "ascii"))
response = str(sock.recv(1024), "ascii")
print("Received: {}".format(response))
def main():
client = Client("localhost", 8080)
client.start("Hello World!")
if __name__ == '__main__':
main()
Then I open two different shell occurences and I do:
$ python3 -m server
The server outputs its message and the shell hangs, which is the expected behavior since I turned daemon mode off and it is supposed to serve forever.
Pinging localhost works fine, all packages are received with no loss. On the other hand, using netstat, I can't seem to find the port I'm opening (8080).
and in the other:
$ python3 -m client
Fails with a ConnectionRefusedError which is the typical error when there is nothing to connect to.
My conclusion for now is that the server is closing the port at some point, I suppose when the main thread dies?
I'm not sure how to fix it though? What's wrong with the current implementation.
Thanks for the help.
I am trying to get this simple python3 code to run in docker using sockets, but I receive the following error. Can someone point me in the right direction. I am just trying to get it to work so i can integrate it into my broader project
File "registrar.py", line 29, in <module>
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
AttributeError: __exit__
Server
import socketserver
import json
list_of_nodes = []
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
global list_of_nodes
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(json.loads(self.data))
# just send back the same data, but upper-cased
list_of_nodes.append(json.loads(self.data))
self.request.sendall(bytes(str(len(list_of_nodes)-1), 'utf-8'))
print(list_of_nodes)
if __name__ == "__main__":
HOST, PORT = "localhost", 58333
# Create the server, binding to localhost on port 9999
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
Client
import socket
import sys
import time
import json
HOST, PORT = "localhost", 58333
data = " ".join(sys.argv[1:])
dict_node = {'nVersion': 1,
'nTime': time.time(),
'addrMe': socket.gethostbyname(socket.gethostname())
}
# Create a socket (SOCK_STREAM means a TCP socket)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
# Connect to server and send data
sock.connect((HOST, PORT))
json_msg = json.dumps(dict_node)
sock.sendall(bytes(json_msg, "utf-8"))
# Receive data from the server and shut down
received = str(sock.recv(1024), "utf-8")
print("Sent: {}".format(json_msg))
print("Received: {}".format(json.loads(received)))
I have made a simple TCP server and client in Python. Everything works fine when I use the local IP of the server, but not with the public IP. My server has a static IP and is bound to this IP and a port, and the client is trying to connect to the public IP with the same port. I've set up port forwarding on my router to supposedly redirect traffic to that port to the server's local IP. The router is a Netgear X4S R7800.
Neither the server nor the client crash at any point. The client just times out eventually and throws an exception, and the server doesn't seem to receive any connection at all.
Server.py
from socket import *
SERVER_NAME = '192.168.1.140' #My server's (static) local IP
SERVER_PORT = 12100
def initializeServer():
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind((SERVER_NAME, SERVER_PORT))
serverSocket.listen(5)
print("Server initialized to port " + str(SERVER_PORT) +"...")
return serverSocket
def serverLoop(serverSocket):
while True:
connectionSocket, addr = serverSocket.accept() #Gets stuck here
print("Connected to", addr)
listenToClient(connectionSocket)
print("Terminating client connection ...")
connectionSocket.close()
if __name__ == '__main__':
serverSocket = initializeServer()
try:
serverLoop(serverSocket)
except KeyboardInterrupt:
shutdownServer(serverSocket)
print("\nServer shut down")
Client.py
import socket
SERVER_NAME = '193.91.XXX.XXX' #Public IP
SERVER_PORT = 12100
def connectToServer(serverName, serverPort):
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect((serverName, serverPort)) #Gets stuck here and eventually times out
return clientSocket
def main():
try:
serverSocket = connectToServer(SERVER_NAME, SERVER_PORT)
except Exception as e:
print("Cannot connect to the server\n", e)
else:
print("Connected to server")
try:
askForUserAction(serverSocket)
except KeyboardInterrupt:
serverSocket.close()
if __name__ == '__main__':
main()
Alright, I solved it. My modem provided by my ISP is apparently also a router. I have another router and I was connected to and forwarding ports from this one. Just had to change the setting of my ISP's router and it worked fine.
SocketServer Program
This code is in raspberry:
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
print self.data
# just send back the same data, but upper-cased
self.request.sendall(self.data)
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
Socket Client Program
This code is in my laptop:
import socket
import sys
HOST, PORT = "192.168.1.40", 3360
data='Hello'
#data = data.join(sys.argv[1:])
# Create a socket (SOCK_STREAM means a TCP socket)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to server and send data
sock.connect((HOST, PORT))
sock.sendall(data + "\n")
# Receive data from the server and shut down
received = sock.recv(1024)
finally:
sock.close()
print "Sent: {}".format(data)
print "Received: {}".format(received)
Here the data sent should be received to server and sent back to client.
This is the error:
[Errno 10061] No connection could be made because the target machine actively refused it.
Try changing to HOST, PORT = "0.0.0.0", 9999 in the server. Now the server should listen on all interfaces and not just the loopback interface. The same could also be achieved using an empty string i.e HOST, PORT = "", 9999.
I am wondering if there is any way to wirelessly connect to a computer/server using python's socket library. The dir(socket) brought up a lot of stuff and I wanted help sorting it out.
but one question. Is the socket server specific to python, or can
another language host and python connect or vise-versa?
As long as you are using sockets - you can connect to any socket-based server (made with any language). And vice-versa: any socket-based client will be able to connect to your server. Moreover it's cross-platform: socket-based client from any OS can connect to any socket-based server (from any OS).
It is unclear of what you mean by "Connect to a computer" so I gave you a TCP socket server and client.
Create a socket server on the computer you wish to "connect to" with:
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
print self.data
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Now create the client:
import socket
import sys
HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])
(SOCK_STREAM means a TCP socket)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
sock.sendall(data + "\n")
received = sock.recv(1024)
finally:
sock.close()
print "Sent: {}".format(data)
print "Received: {}".format(received)
You run the server and then the client and the server should receive the client's connection and send it whatever you have as the data variable on the server. Source: https://docs.python.org/2/library/socketserver.html