Having a small problem with a multithreaded socket server in Python 3. I can't seem to start my socket listening in its own thread. I'm probably way off base.
Borrowed the code here: How to make a simple multithreaded socket server in Python that remembers clients
But I need to listen for clients within a thread or at least in the background. Can't figure out what I'm doing wrong.
Here's my code:
import socket
from threading import Thread
from cmd import Cmd
class ThreadedServer(Thread):
def __init__(self):
self.host = "127.0.0.1"
self.port = int(8080)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
def listen(self):
self.sock.listen(5)
print("[Info]: Listening for connections on {0}, port {1}".format(self.host,self.port))
while True:
print("Hello?") # Just debug for now
client, address = self.sock.accept()
client.settimeout(60)
threading.Thread(target = self.listenToClient,args = (client,address)).start()
def listenToClient(self, client, address):
size = 1024
while True:
try:
data = client.recv(size)
if data:
# Set the response to echo back the recieved data
response = data
client.send(response)
else:
raise error('Client disconnected')
except:
client.close()
return False
class CommandInput(Cmd):
# Able to accept user input here but is irrelevant right now
pass
print("[Info]: Loading complete.")
clientThread = ThreadedServer().listen()
clientThread.start()
print("[Info]: Server ready!")
prompt = CommandInput()
prompt.prompt = '> '
prompt.cmdloop("[Info]: Type \'help\' for a list of commands and their descriptions/use")
As you can see I have some code after my listening part where I need to be able to accept input on the terminal. However, the code never gets there.
Here's the output quite simply:
[Info]: Loading complete.
[Info]: Listening for connections on 127.0.0.1, port 8080
Hello?
I'm expecting:
[Info]: Loading complete.
[Info]: Listening for connections on 127.0.0.1, port 8080
Hello?
[Info]: Type \'help\' for a list of commands and their descriptions/use
>
with a cursor ready for me to type.
So how can I properly get my program to listen for clients in that loop in a proper thread so that I can enter prompts at the command line and process user input (for example one of the commands I want to implement is that of a client "send" which I would be able to send debug information to connected clients)
Thanks for any assistance you can provide.
This may not be the ideal structure for setting up what you want, but seems to solve the requirement you stated.
After launching this script on a terminal, you can make sample client connections by opening one, or more, browser tabs to localhost:8080
import socket
from threading import Thread
from cmd import Cmd
# basic threading tutorial: https://www.tutorialspoint.com/python3/python_multithreading.htm
class ThreadedServer(Thread):
def __init__(self):
Thread.__init__(self) # change here
self.host = "127.0.0.1"
self.port = int(8080)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
def run(self): # change here
self.sock.listen(5)
print("[Info]: Listening for connections on {0}, port {1}".format(self.host,self.port))
while True:
print("Hello?") # Just debug for now
client, address = self.sock.accept()
client.settimeout(60)
Thread(target = self.listenToClient, args = (client,address)).start() # change here
def listenToClient(self, client, address):
size = 1024
while True:
try:
data = client.recv(size)
if data:
# Set the response to echo back the recieved data
response = data
client.send(response)
else:
raise error('Client disconnected')
except:
client.close()
return False
class CommandInput(Cmd):
# Able to accept user input here but is irrelevant right now
pass
if __name__ == "__main__":
print("[Info]: Loading complete.")
server = ThreadedServer() # change here
server.start() # change here
print("[Info]: Server ready!")
prompt = CommandInput()
prompt.prompt = '> '
prompt.cmdloop("[Info]: Type \'help\' for a list of commands and their descriptions/use")
Okay, so I createda socket server in python and I want when someone connects to it to run an application on the sever but which is user controlled. I'll try to explain better with the code.
#!/usr/bin/python
import socket
import select
import os
from time import sleep
class SocketServer:
""" Simple socket server that listens to one single client. """
def __init__(self, host = '0.0.0.0', port = 2010):
""" Initialize the server with a host and port to listen to. """
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.host = host
self.port = port
self.sock.bind((host, port))
self.sock.listen(1)
def close(self):
""" Close the server socket. """
print('Closing server socket (host {}, port {})'.format(self.host, self.port))
if self.sock:
self.sock.close()
self.sock = None
def run_server(self):
""" Accept and handle an incoming connection. """
print('Starting socket server (host {}, port {})'.format(self.host, self.port))
client_sock, client_addr = self.sock.accept()
print('Client {} connected'.format(client_addr))
stop = False
while not stop:
if client_sock:
# Check if the client is still connected and if data is available:
os.system("python vuln.py")
# try:
# rdy_read, rdy_write, sock_err = select.select([client_sock,], [], [])
# except select.error:
# print('Select() failed on socket with {}'.format(client_addr))
# return 1
if len(rdy_read) > 0:
read_data = client_sock.recv(255)
if len(read_data) == 0:
print('{} closed the socket.'.format(client_addr))
stop = True
else:
print('>>> Received: {}'.format(read_data.rstrip()))
if read_data.rstrip() == 'quit':
stop = True
else:
client_sock.send(read_data)
else:
print("No client is connected, SocketServer can't receive data")
stop = True
# Close socket
print('Closing connection with {}'.format(client_addr))
client_sock.close()
return 0
def main():
server = SocketServer()
while (True):
server.run_server()
print 'Exiting'
if __name__ == "__main__":
main()
This is my socket server, which always runs and cand establish multiple connections.
print("Please tell me what's your age")
age = input('> ')
sleep(1)
print("Damn man, sometimes I wish I was %s" % age)
sleep(1)
and this is the app which I want to run on the server and let the user who connects with netcat for example see the same prompt and have the same functionality but on the server.
I made this basic Python 3 socket server in an attempt to learn socket programming. I can connect to it using 'telnet 192.168.x.x 9001' on the same computer, running Ubuntu 16.04, but when I try using my other computer on a different network, Windows 10, on a different network it wont let me connect (when using the computer running Windows 10, I run the serve on Ubuntu).
This is the code I have written.
import socket
from _thread import start_new_thread
host = ""
port = 9001
class Server:
def __init__(self, host, port):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.server.bind((host, port))
except socket.error as e:
print(str(e))
self.server.listen(10)
def main(self, conn):
while True:
conn.send(str.encode("Enter some text to make uppercase: "))
message = conn.recv(4096)
message = str(message,'utf-8')
conn.send(str.encode(message.upper()))
def run(self):
while True:
conn, addr = self.server.accept()
print("Connection from {}:{:d}".format(addr[0], addr[1]))
start_new_thread(self.main, (conn, ))
my_server = Server(host, port)
my_server.run()
I'm am trying to write a client program in Python that can send and receive from the same socket, but it is always giving me the same error which address is already in use. Here is the function I'm trying to write.
def Login():
username=raw_input()
password=raw_input()
message=raw_input()
array=[username,password,message]
TCP_IP = '127.0.0.1'
TCP_PORT = 5563
BUFFER_SIZE = 1024 # Normally 1024, but we want fast response
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((TCP_IP, TCP_PORT))
array_string=pickle.dumps(array)
sock.send(array_string)
sock.close()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((TCP_IP, TCP_PORT))
sock.listen(1)
conn, info = sock.accept()
while 1:
data = serverSocket.recv(1024)
if not data:break
conn.send(data)
conn.close()
There is a bunch of truly newbie errors here.
You can't ever connect a TCP socket to itself. There must be two different sockets.
If you really want to get the data you sent earlier at a listening socket, this listening socket must be created, bound and configured to listen before the client side connects (or, at least, in parallel to this connect attempt, in a few seconds, so the connect attempt will try - but this very likely won't work on localhost).
You can't wait on connect and on accept in the same thread if both are blocking. The simplest approach is to separate the client side and the server side to 2 different programs and run them manually in parallel. Then, after successful debugging, you will be able to do this in different threads of the same process, or using an event-driven engine.
While you may not be able to connect a socket to itself to send and receive data, you might be able to learn from the following example inspired by your code that attempts to do something similar.
import _thread
import pickle
import socket
import time
def main():
"""Run a server in a thread and start a client to talk to it."""
_thread.start_new_thread(run_server, ('', 5563))
run_client('localhost', 5563)
def run_server(host, port):
"""Handle all incoming connections by spawning worker threads."""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(5)
while True:
_thread.start_new_thread(handle_connection, server.accept())
def handle_connection(client, address):
"""Answer an incoming question from the connected client."""
print('Incoming connection from', address)
client.settimeout(0.1)
data = recvall(client)
client.shutdown(socket.SHUT_RD)
question = pickle.loads(data)
answer = '''len(username) = {}
len(password) = {}
len(message) = {}'''.format(*map(len, question))
client.sendall(answer.encode())
client.shutdown(socket.SHUT_WR)
client.close()
print('Finished with', address)
def recvall(connection):
"""Receive all data from a socket and return as a bytes object."""
buffer = bytearray()
while True:
try:
data = connection.recv(1 << 12)
except socket.timeout:
pass
else:
if data:
buffer.extend(data)
else:
return bytes(buffer)
def run_client(host, port):
"""Collect information from question and display returned answer."""
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
time.sleep(0.1) # wait for server to start listening for clients
client.connect((host, port))
time.sleep(0.1) # wait for handler thread to display connection
username = input('Username: ')
password = input('Password: ')
message = input('Message: ')
question = pickle.dumps((username, password, message))
client.sendall(question)
client.shutdown(socket.SHUT_WR)
answer = recvall(client)
client.shutdown(socket.SHUT_RD)
client.close()
print(answer.decode())
time.sleep(0.1) # wait for handler to cleanly terminate execution
if __name__ == '__main__':
main()
How can I know if a certain port is open/closed on linux ubuntu, not a remote system, using python?
How can I list these open ports in python?
Netstat:
Is there a way to integrate netstat output with python?
You can using the socket module to simply check if a port is open or not.
It would look something like this.
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex(('127.0.0.1',80))
if result == 0:
print "Port is open"
else:
print "Port is not open"
sock.close()
If you want to use this in a more general context, you should make sure, that the socket that you open also gets closed. So the check should be more like this:
import socket
from contextlib import closing
def check_socket(host, port):
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
if sock.connect_ex((host, port)) == 0:
print("Port is open")
else:
print("Port is not open")
For me the examples above would hang if the port wasn't open. Line 4 shows use of settimeout to prevent hanging
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2) #2 Second Timeout
result = sock.connect_ex(('127.0.0.1',80))
if result == 0:
print 'port OPEN'
else:
print 'port CLOSED, connect_ex returned: '+str(result)
If you only care about the local machine, you can rely on the psutil package. You can either:
Check all ports used by a specific pid:
proc = psutil.Process(pid)
print proc.connections()
Check all ports used on the local machine:
print psutil.net_connections()
It works on Windows too.
https://github.com/giampaolo/psutil
Here's a fast multi-threaded port scanner:
from time import sleep
import socket, ipaddress, threading
max_threads = 50
final = {}
def check_port(ip, port):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP
#sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
socket.setdefaulttimeout(2.0) # seconds (float)
result = sock.connect_ex((ip,port))
if result == 0:
# print ("Port is open")
final[ip] = "OPEN"
else:
# print ("Port is closed/filtered")
final[ip] = "CLOSED"
sock.close()
except:
pass
port = 80
for ip in ipaddress.IPv4Network('192.168.1.0/24'):
threading.Thread(target=check_port, args=[str(ip), port]).start()
#sleep(0.1)
# limit the number of threads.
while threading.active_count() > max_threads :
sleep(1)
print(final)
Live Demo
I found multiple solutions in this post. But some solutions have a hanging issue or takeing too much time in case of the port is not opened.Try below solution :
import socket
def port_check(HOST):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2) #Timeout in case of port not open
try:
s.connect((HOST, 22)) #Port ,Here 22 is port
return True
except:
return False
port_check("127.0.1.1")
In case when you probing TCP ports with intention to listen on it, it’s better to actually call listen. The approach with tring to connect don’t 'see' client ports of established connections, because nobody listen on its. But these ports cannot be used to listen on its.
import socket
def check_port(port, rais=True):
""" True -- it's possible to listen on this port for TCP/IPv4 or TCP/IPv6
connections. False -- otherwise.
"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', port))
sock.listen(5)
sock.close()
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.bind(('::1', port))
sock.listen(5)
sock.close()
except socket.error as e:
return False
if rais:
raise RuntimeError(
"The server is already running on port {0}".format(port))
return True
Building upon the psutil solution mentioned by Joe (only works for checking local ports):
import psutil
1111 in [i.laddr.port for i in psutil.net_connections()]
returns True if port 1111 currently used.
psutil is not part of python stdlib, so you'd need to pip install psutil first. It also needs python headers to be available, so you need something like python-devel
Agree with Sachin. Just one improvement, use connect_ex instead of connect, which can avoid try except
>>> def port_check(ip_port):
... s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
... s.settimeout(1)
... return s.connect_ex(ip_port) == 0
...
>>> port_check(loc)
True
>>> port_check(loc_x)
False
>>> loc
('10.3.157.24', 6443)
>>>
Just added to mrjandro's solution some improvements like automatic resource management (making sure that the opened socket also gets closed), handling timeouts, getting rid of simple connection errors / timeouts and printing out results:
import socket
from contextlib import closing
hosts = ["host1", "host2", "host3"]
port = 22
timeout_in_seconds = 2
hosts_with_opened_port = []
hosts_with_closed_port = []
hosts_with_errors = []
def check_port(host, port, timeout_in_seconds):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout_in_seconds)
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
try:
result = sock.connect_ex((host, port))
if result == 0:
print("Port {} is *** OPEN *** on host: {}".format(port, host))
hosts_with_opened_port.append(host)
else:
print("Port {} is not open on host: {}".format(port, host))
hosts_with_closed_port.append(host)
except socket.gaierror:
print("Port {} check returns a network *** ERROR *** on host: {}".format(port, host))
hosts_with_errors.append(host)
for host in hosts:
check_port(host, port, timeout_in_seconds)
print("\nHosts with opened port:")
print(hosts_with_opened_port)
print("\nHosts with closed port:")
print(hosts_with_closed_port)
print("\nHosts with errors:")
print(hosts_with_errors)
Netstat tool simply parses some /proc files like /proc/net/tcp and combines it with other files contents. Yep, it's highly platform specific, but for Linux-only solution you can stick with it. Linux kernel documentation describes these files in details so you can find there how to read them.
Please also notice your question is too ambiguous because "port" could also mean serial port (/dev/ttyS* and analogs), parallel port, etc.; I've reused understanding from another answer this is network port but I'd ask you to formulate your questions more accurately.
Please check Michael answer and vote for it. It is the right way to check open ports. Netstat and other tools are not any use if you are developing services or daemons. For instance, I am crating modbus TCP server and client services for an industrial network. The services can listen to any port, but the question is whether that port is open? The program is going to be used in different places, and I cannot check them all manually, so this is what I did:
from contextlib import closing
import socket
class example:
def __init__():
self.machine_ip = socket.gethostbyname(socket.gethostname())
self.ready:bool = self.check_socket()
def check_socket(self)->bool:
result:bool = True
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
modbus_tcp_port:int = 502
if not sock.connect_ex((self.machine_ip, modbus_tcp_port)) == 0:
result = False
return result
This will find a random port in the given range:
import socket
import random
from typing import Tuple
def find_listening_port(
port_range:Tuple[int,int]=None,
host='',
socket_type='tcp',
default:int=None
) -> int:
"""Find an available listening port
Arguments:
port_range: Optional tuple of ports to randomly search, ``[min_port, max_port]``
If omitted, then randomly search between ``[6000, 65534]``
host: Host interface to search, if omitted then bind to all interfaces
socket_type: The socket type, this should be ``tcp`` or ``udp``
default: The port to try first before randomly searching the port range
Returns:
Available port for listening
"""
def _test_port(host, port, socket_protocol):
with socket.socket(socket.AF_INET, socket_protocol) as sock:
try:
sock.bind((host, port))
if socket_type == 'tcp':
sock.listen(1)
return port
except:
pass
return -1
if port_range is None:
port_range = (6000,65534)
if socket_type == 'tcp':
socket_protocol = socket.SOCK_STREAM
elif socket_type == 'udp':
socket_protocol = socket.SOCK_DGRAM
else:
raise Exception('Invalid socket_type argument, must be: tcp or udp')
searched_ports = []
if default is not None:
port = _test_port(host, default, socket_protocol)
if port != -1:
return port
searched_ports.append(default)
for _ in range(100):
port = random.randint(port_range[0], port_range[1])
if port in searched_ports:
continue
port = _test_port(host, port, socket_protocol)
if port != -1:
return port
searched_ports.append(port)
raise Exception(f'Failed to find {socket_type} listening port for host={host}')
Example usage:
# Find a TCP port,
# first check if port 80 is availble
port = find_listening_port(
port_range=(4000, 60000),
host='',
socket_type='tcp',
default=80
)
print(f'Available TCP port: {port}')