closing open socket in python - python

Im wondering is there any way to find out the socket that is open and then to close it?
For instance,I have a script "SendInfo.py" which opens a socket and sends some info over TCP.
If I call this script to run it e.g. "python SendInfo.py" , it will open a new socket.
If I run this script again using "python SendInfo.py", which will send some more up to date information, I would like to cancel the previous TCP transaction and start a new one - e.g. by closing the previous socket.
How do I get access to the open socket at the beginning of my script in order to close it? Ive tried looking into threads, but Im similarly confused about which threads are open and how to close open threads etc.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.settimeout(2)
s.connect((self.__host, PORT))

I'm not sure if this is what you are after but here is a method of ensuring that the script is only running once and killing an existing running script.
You may find something useful in it. (This is for Linux)
#!/usr/bin/python
# running.py
# execute by making the script executable
# put it somewhere on $PATH and execute via running.py
# or execute via ./running.py
import os, sys, time , signal, socket
running_pid = os.popen('ps --no-headers -C running.py').read(5)
try:
running_pid = int(running_pid)
except:
running_pid = 0
current_pid = int(os.getpid())
if running_pid != 0:
if running_pid != current_pid:
print "Already running as process", running_pid
print "Killing process", running_pid
os.kill(int(running_pid), signal.SIGKILL)
# sys.exit()
# Create a listening socket for external requests
tcp_port = 5005
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print "Error on Socket 5005"
# force re-use of the socket if it is in time-out mode after being closed
# other wise we can get bind errors after closing and attempting to start again
# within a minute or so
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.settimeout(0.10)
sock.bind(("localhost", tcp_port))
except IOError as msg:
print "Error on Socket Bind "+str(tcp_port)+", running.py is probably already running"
pass
try:
sock.listen((1))
except:
print "Error on Socket listen"
time.sleep(60)
sock.close()

Related

How to create Python API or network requests hidden (protected from hackers checking network traffic) on Local Network to manage Computers

I know that I can see inside of network traffic for example with WireShark. When i use GET on HTML I can see those stuff in URL, what should not be problem what I am doing. But I believe GET,POST and maybe REQUEST too, as I did not work with that one yet can bee seen on something like Wire Shark network analyzer.
I am making Python client, what i will put on computers in network to show their IP,Host Name and Users on PC. This client will be as gate to the computer for remote control. As our management does not want to spend money for windows server, or other management system we need to get something free to manage all computers.
I am also seeking advice how I could do it as you are more skilled then me here.
I found few ways.
With the client create SSH Gateway for receiving commands.
With Client enable the Powershell remote option, then just push scripts to all computers at once.
Use some way the API requests etc... I am not skilled in this one at all, but I believe this is the way how other similar programs works?
As this client would create big security risk, I am first seeking way what is best way to hide it from network. Probably I will need to come up with some Private and public Key system here as well.
What are yours suggestions please on this topic?
here is just very short code I am playing with to receive basic info as IP, Host name and all Users
the Flask website showing those values is just for test, It will not be there once it is deployed
Update
I took advice from MarulForFlask but I got a couple issues. First this i think can have only one connection at a time. And second if possible Can i get the output of console from the client PC on screen of Server PC?
I want this output only for testing, as I know if i do something like netstat or any other command with multiple clients it would filled up screen with too many text... Currently I am getting back text format as plaintext with \r \n ... and other text deviders.
I am now trying Multicast, but i am getting error for binding the multicast IP.
OSError: [WinError 10049] The requested address is not valid in its context
Master.py
import time
import socket
import sys
import os
valueExit = True
# Initialize s to socket
s = socket.socket()
# Initialize the host
host = socket.gethostname()
BUFFER_SIZE = 1024
# Initialize the port
port = 8080
# Bind the socket with port and host
s.bind(('', port))
print("waiting for connections...")
# listening for conections
s.listen()
# accepting the incoming connections
conn, addr = s.accept()
print(addr, "is connected to server")
def send_query():
keepAllive, repeatIt = True, False
print("""To exit session write: EndSession
For help write: help
""")
while (keepAllive == True):
# commands for server use only
innerCommands = ["endsession", "help"]
# take command as input
command = input(str("Enter Command : "))
if command not in innerCommands:
conn.send(command.encode())
print("Command has been sent successfully.")
keepAllive = False
repeatIt = True
elif (command == "endsession"):
conn.send(command.encode())
valueExit = False
elif (command == "help"):
print("""To exit session write: EndSession""")
while (repeatIt == True):
# recieve the confrmation
data = conn.recv(BUFFER_SIZE)
if data:
print(f"command recieved and executed sucessfully.\n {data}")
keepAllive = True
repeatIt = False
else:
print("No reply from computer")
keepAllive = True
repeatIt = False
while valueExit == True:
send_query()
Slave.py
import time
import socket
import sys
import subprocess
import os
stayOn = True
def establishConnection():
# Initialize s to socket
s = socket.socket()
# Initialize the host
host = "127.0.0.1"
# Initiaze the port
port = 8080
keepAlive = True
try:
# bind the socket with port and host
s.connect((host, port))
print("Connected to Server.")
while keepAlive == True:
# recieve the command from master program
command = s.recv(1024)
command = command.decode()
# match the command and execute it on slave system
if command == "endsession":
print("Program Ended")
keepAlive = False
elif command != "":
# print("Command is :", command)
#s.send("Command recieved".encode())
proc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
s.send(f"{out}".encode())
print("program output:", out)
except Exception as err:
print(f"Error: {err}")
s.send(f"Error: {err}".encode())
while stayOn == True:
establishConnection()
see:
https://www.pythonforthelab.com/blog/how-to-control-a-device-through-the-network/
There uses a flask webserver.
otherwise, create a master.py file and paste this code:
import time
import socket
import sys
import os
# Initialize s to socket
s = socket.socket()
# Initialize the host
host = socket.gethostname()
# Initialize the port
port = 8080
# Bind the socket with port and host
s.bind(('', port))
print("waiting for connections...")
# listening for conections
s.listen()
# accepting the incoming connections
conn, addr = s.accept()
print(addr, "is connected to server")
# take command as input
command = input(str("Enter Command :"))
conn.send(command.encode())
print("Command has been sent successfully.")
# recieve the confrmation
data = conn.recv(1024)
if data:
print("command recieved and executed sucessfully.")
open a slave.py and paste this code:
import time
import socket
import sys
import os
# Initialize s to socket
s = socket.socket()
# Initialize the host
host = "127.0.0.1"
# Initiaze the port
port = 8080
# bind the socket with port and host
s.connect((host, port))
print("Connected to Server.")
# recieve the command from master program
command = s.recv(1024)
command = command.decode()
# match the command and execute it on slave system
if command == "open":
print("Command is :", command)
s.send("Command recieved".encode())
# you can give batch file as input here
os.system('ls')
open slave.py in client, master.py in server
https://www.geeksforgeeks.org/how-to-control-pc-from-anywhere-using-python/

Python socket.accept() blocking code before call?

I am trying to learn Python sockets and have hit a snare with the socket.accept() method. As I understand the method, once I call accept, the thread will sit and wait for an incoming connection (blocking all following code). However, in the code below, which I got from https://docs.python.org/2/library/socket.html and am using localhost. I added a print('hello') to the first line of the server. Yet the print doesn't appear until after I disconnect the client. Why is this? Why does accept seem to run before my print yet after I bind the socket?
# Echo server program
import socket
print('hello') # This doesn't print until I disconnect the client
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
# Echo client program
import socket
HOST = 'localhost' # The remote host
PORT = 50007 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)
You are likely using an output device on a system that Python's IO doesn't recognize as interactive. As a workaround, you can add sys.stdout.flush() after the print.
The standard output is a buffered stream, meaning that when you print something, the output sticks around in an internal buffer until you print enough data to fill the whole buffer (unlikely in a small program, the buffet is several kilobytes in size), or until the program exits, when all such buffers are automatically flushed. Normally when the output is a terminal service, the IO layer automatically switches to line buffering, where the buffer is also flushed whenever a newline character is printed (and which the print statement inserts automatically).
For some reason, that doesn't work on your system, and you have to flush explicitly. Another option is to run python -u, which should force unbuffered standard streams.

Reconnecting a Bluetooth device using socket library (RFCOMM mode) in python 3?

I am trying to connect to a Bluetooth GPS unit from a Raspberry Pi3 using the socket library in python 3. I am able to connect and get data flowing the first time but if I disconnect and then try reconnecting I get:
[Errno 16] Device or resource busy
I have tried placing the connection in a sub process killing it and recreating it (end goal) and I get the same error. If I close and restart the test program it connects no problem.
Here is a test script based on a demo I found, that opens the connection closes it then tries to reconnect for ever. When I try it I get tick tick tick... until I hit ^c to kill it
import io
import socket
from time import sleep
from bluetooth import *
import sys
class SocketIO(io.RawIOBase):
def __init__(self, sock):
self.sock = sock
def read(self, sz=-1):
if (sz == -1): sz=0x7FFFFFFF
return self.sock.recv(sz)
def seekable(self):
return False
# file: l2capclient.py
# desc: Demo L2CAP client for bluetooth module.
# $Id: l2capclient.py 524 2007-08-15 04:04:52Z albert $
if sys.version < '3':
input = raw_input
if len(sys.argv) < 2:
print("usage: l2capclient.py <addr>")
sys.exit(2)
bt_addr=sys.argv[1]
port = 1
print("trying to connect to %s on PSM 0x%X" % (bt_addr, port))
# Create the client socket
sock=BluetoothSocket( RFCOMM )
sock.connect((bt_addr, port))
fd = SocketIO(sock)
bno = 0
for line in fd:
print(line)
bno +=1
if bno >10:
break
sock.shutdown(socket.SHUT_RDWR)
sock.close()
print("closed")
sock=BluetoothSocket( RFCOMM )
not_connected = True
while not_connected:
try:
sock.connect((bt_addr, port))
not_connected = False
except:
sleep(1)
print("tick")
pass
fd = SocketIO(sock)
try:
for line in fd:
print(line)
except IOError:
pass
sock.close()
The SocketIO class is just for convenience of getting data line by line I have tried it with sock.recv(1024) and got the same results.
I have a similar issue. I send data to an HC-05 bluetooth module from my PC using python sockets and a bluetooth RFCOMM socket. Here are a few things which have seemed to improve the debugging situation working with bluetooth...
If you havent already, make your socket a nonblocking socket, it sends out a flag when something goes wrong instead of crashing the program
Make sure you close the connection properly (it seems that you are doing that though)
Make sure that the GPS has no factory settings that prevent you from connecting instantly again. It could maybe have to do with a factory setting/timeout thing not agreeing with the way you request to connect again, and that error could be due to your code and quite possibly in a factory setting if there are any.

Multithreaded webserver in Python

An example from a video lecture. Background: the lecturer gave a simplest web server in python. He created a socket, binded it, made listening, accepted a connection, received data, and send it back to the client in uppercase. Then he said that there is a drawback: this web server is single-threaded. Then let's fork.
I can't understand the example well enough. But to start with, the program exits (sys.exit()). But I can't run it again:
socket.error: [Errno 98] Address already in use.
I try to find out which process is listening on port 8080: netstat --listen | grep 8080. Nothing.
Well, what is listening on 8080? And how to kill it?
Added later:
There is a feeling that if I wait for some time (say, 5-10 minutes), I can run the program again.
import os
import socket
import sys
server_socket = socket.socket()
server_socket.bind(('', 8080))
server_socket.listen(10)
print "Listening"
while True:
client_socket, remote_address = server_socket.accept()
print "PID: {}".format(os.getpid())
child_pid = os.fork()
print "child_pid {}".format(child_pid)
if child_pid == 0:
request = client_socket.recv(1024)
client_socket.send(request.upper())
print '(child {}): {}'.format(client_socket.getpeername(), request)
client_socket.close()
sys.exit()
else:
client_socket.close()
server_socket.close()
The correct netstat usage is:
netstat -tanp
because you need the -a option to display listening sockets. Add grep to locate your program quickly:
netstat -tanp| grep 8080

Run a python socket server and if closed remotely start it listening again

I am struggling to get my python socket to behave.
There are two major problems:
1) When it listens for the client connection the program stalls which is a problem because it is running on a IRC client python interpreter causing the IRC client not to respond until the client connects.
2) When the client disconnects the entire script has to be stopped and then restarted again inorder to get the socket server to listen once more.
I thought the way around it might be to start the socket listening in a separate thread, so the IRC client can continue while it waits for the client connection. Also, once the client has decided to close the connection I need a way restart it.
The following code is terrible and doesn't work but it might give you an idea as to what I'm attempting:
__module_name__ = "Forward Module"
__module_version__ = "1.0.0"
__module_description__ = "Forward To Flash Module by Xcom"
# Echo client program
import socket
import sys
import xchat
import thread
import time
HOST = None # Symbolic name meaning all available interfaces
PORT = 7001 # Arbitrary non-privileged port
s = None
socketIsOpen = False
def openSocket():
# start server
print "starting to listen"
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC,
socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
af, socktype, proto, canonname, sa = res
try:
s = socket.socket(af, socktype, proto)
except socket.error as msg:
s = None
continue
try:
s.bind(sa)
s.listen(1)
except socket.error as msg:
s.close()
s = None
continue
break
if s is None:
print 'could not open socket'
global socketIsOpen = False
sys.exit(1)
conn, addr = s.accept()
print 'Connected by', addr
global socketIsOpen = True
def someone_said(word, word_eol, userdata):
username = str(word[0])
message = str(word[1])
sendMessage = username + " : " + message
send_to_server(sendMessage)
def send_to_server(message):
conn.send(message)
def close_connection():
conn.close()
print "connection closed"
xchat.hook_print('Channel Message' , someone_said)
def threadMethod(arg) :
while 1:
if (not socketIsOpen) :
openSocket()
try:
thread.start_new_thread(threadMethod, args = [])
except:
print "Error: unable to start thread"
The python is running on an IRC client called HexChat which is where the xchat import comes from.
The way you usually program a threaded socket server is:
call accept() in a loop
spawn a new thread to handle the new connection
A very minimal example would be somethig like this:
import socket
import threading
import time
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 9999))
server.listen(1)
def handle(conn):
conn.send(b'hello')
time.sleep(1) # do some "heavy" work
conn.close()
while True:
print('listening...')
conn, addr = server.accept()
print('handling connection from %s' % (addr,))
threading.Thread(target=handle, args=(conn,)).start()
You're spawning new threads in which you create your listening socket, then accept and handle your connection. And while socketIsOpen is True your programm will be using a lot of cpu looping through your while loop doing nothing. (btw, the way you check socketIsOpen allows for race conditions, you can start multiple threads before it is set.)
And one last thing, you should try to use the threading module instead of the deprecated thread.

Categories