Python, Closed vs Timed Out Ports? - python

I have been looking for a solution for this problem since days but wasn't able to find any, I'm interested in knowing which ports are closed (ie there is host that returned that this port is closed) and which are timed out.
My current code:
ssdpDiscover = (
'M-SEARCH * HTTP/1.1\r\n' + 'HOST: ' + ip + ':1900\r\n' + 'MAN: "ssdp:discover"\r\n' + 'MX: 1\r\n' + 'ST: ssdp:all\r\n' + '\r\n')
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.sendto(ssdpDiscover.encode('ASCII'), (ip, UPnP_PORT))
sock.settimeout(3) #seconds
while 1:
data, address = sock.recvfrom(BUFFER_SIZE)
upnp_obj['state'] = 'open'
location_result = location_regex.search(data.decode('ASCII'))
if location_result:
location = location_result.group(1)
break
except socket.timeout:
upnp_obj['state'] = 'timeout'
How can I detect if the host sent back a message telling if port is closed or not?

Related

python socket / how do you detect disconnection from clients and detect number of connections per user

this is for server authentication for my application.
(im working on login function so dont mind about it)
what i wanna do is to make server receive heartbeat from client
and close client socket if its doesnt respond in a few min
also i want to detect number of connections per user.
for receiving heartbeat, i can make the client send heartbeat constantly but
how do you make the server decect it? i know time measurement is needed but
if i put time.perf_counter() right before 'client_socket.recv(1024)' the counter function wont be executed because its waiting on receiving. so how would i solve this?
and im also trying to make it detect number of connections per user. (5 maximum connections per user) for detection, i give username + 1 when a user is connected and give -1 when the user disconnects but im not sure if the method im doing is correct or a good way to do so.
i'd be appreciated if you could help me out
------------------------server----------------------------
import socket
from _thread import *
import sys
import time
username = ['test123', 'hongengi']
userconnect= 0
def threaded(client_socket, addr):
print('Connected by :', addr[0], ':', addr[1])
while True:
try:
data = client_socket.recv(1024)
print (data.decode())
print('Received from ' + addr[0],':',addr[1] , data.decode())
if data.decode() == ".": # heartbeat
heartbeat = time.perf_counter()
print ("heartbeat")
if data.decode() == "test123":
print ("login success")
userconnect == userconnect + 1
if not data:
print ("no data / disconnect ")
print('Disconnected by ' + addr[0],':',addr[1])
userconnect == userconnect - 1
break
client_socket.send(data)
except (ConnectionResetError, socket.error) as e:
print ("error occurs")
print('Disconnected by ' + addr[0],':',addr[1])
userconnect == userconnect - 1
break
client_socket.close()
HOST = '127.0.0.1'
PORT = 5000
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen()
print('server start')
while True:
print('wait')
client_socket, addr = server_socket.accept()
start_new_thread(threaded, (client_socket, addr))
server_socket.close()
------------------------client----------------------------
import socket
SERVER_IP = 'localhost'
SERVER_PORT = 5000
SIZE = 100
SERVER_ADDR = (SERVER_IP, SERVER_PORT)
heartbeat = "."
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(SERVER_ADDR)
#username = "test123"
#userpass = "123123"
while True:
client_socket.send(heartbeat.encode())
msg = client_socket.recv(SIZE)
print (msg.decode())
One end of a socket is never "notified" when the other socket closes. There is no direct connection, so the only way to tell this is to time out. You can use socket.timeout to establish a timeout time. Your recv will then return with 0 bytes, and that's an indication that your timeout expired.
How to set timeout on python's socket recv method?

python server finished but not listening

I have created this server for a project of mine and it finishes with no errors, but I want it to listen for incoming connections here is the code
import socket
import sys
def socket_cr():
try:
global host
global port
global s
host = ''
port = 9999
s= socket.socket()
except socket.error as msg:
print("socket creatin error " + (str(msg)))
socket_cr()
def socket_bind():
try:
global host
global port
global s
print("binding to port :" + str(port))
s.bind((host, port))
s.listen(5)
except socket.error as msg:
print("Socket binding error" + str(msg) + "\n" + "retrying")
socket_bind()
def socket_acept():
conn, address = s.accept()
print("connection has been astablished | " + "IP" + address[0] + "| port" + str(address[1]))
def send_command(conn):
while True:
cmd = input()
if cmd == 'quite':
conn.close()
s.close()
sys.exit()
if len(str.encode(cmd)) > 0:
conn.send(str.encode(cmd))
client_response = str(conn.recv(1034), "utf-8")
print(client_response, end="")
def main():
socket_cr()
socket_bind()
socket_acept()
main()
and the output is:
Process finished with exit code 0
put it should be binding socket to port 9999
Your code has quite a few problems. If you don't mind, I will rewrite the whole code for you.
Revised code:
import socket
import sys
#No need to define functions for everything OR make the variables global every time.
try:
HOST = ''
PORT = 9999
s = socket.socket()
except socket.error as msg:
#You don't need to convert msg to a string since it's already a string.
print('Socket creating error '+ msg)
print('Binding to port: '+ str(PORT))
try:
s.bind((HOST, PORT))
except socket.error as msg:
print('Socket binding error '+msg+'\nRetrying.')
s.listen(5)
while True:
conn, address = s.accept()
# Address is not an iterable, you can't index elements in it. Address is the IP of the device you have just connected to.
print('Connection has been established | IP '+ address)
cmd = input()
if cmd == 'quit':
# You can end the connection with only a s.close()
s.close()
sys.exit()
#encode is a method of a string, not a function.
# Also, you have to specify how you want to encode the string e.g. mystring.encode('ascii')
#Since it isn't specified, I'll assume it's ascii.
if len(cmd.encode('ascii')) > 0:
conn.send(cmd.encode('ascii'))
# If the client is sending it encoded in ascii as well, instead of str(), you should decode it
client_response = conn.recv(1034).decode('ascii')
print(client_response, end='')
As you can see, defining functions for all of them is unnecessary and it makes the code unclean. Now, you should define the variables at the very beginning of the code if possible. And, you should make the host 0.0.0.0 to ensure public visibilty.
Now, remember, that functions should not be overused.
Happy to help.

How do i get the socket to continue listening to the client and continuosly print information from the client

Server Side (server prints the first line of information sent from the client then it JUST STAYS open and doesn't seem to continue listening it just stays open. Is there a way to get the server to listen to the client more and print?)
import time
import socket
import signal
from datetime import datetime
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 8089))
serversocket.listen(1024) # become a server socket, maximum 5 connectionn
def clientsocketentry():
while True:
connection, addr = serversocket.accept()
buf = connection.recv(64)
if not buf:
break
elif buf == 'killsrv':
connection.close()
sys.exit()
else:
print (buf)
buf = buf.decode("utf-8")
buf = buf.split(',')
serverLong = buf[0]
print('Longitude:' + '' + serverLong)
serverLat = buf[1]
print('Lattitude:' + '' + serverLat)
serverAlt = buf[2]
print('Altitude:' + '' + serverAlt)
serverTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print('Time of Entry:' + ' ' + serverTime)
connection.close()
clientsocketentry()
Client Side (I am only able to send one of the strings of information then the server stays open ut does not take more information from the client)
import socket
import time
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('localhost', 8089))
a = '39.163100,-76.899428,0'
clientsocket.send(a.encode('utf-8'))
time.sleep(5)
a = '4.2,2.2415,0'
clientsocket.send(a.encode('utf-8'))
time.sleep(5)
a = '43454,354354,35435'
clientsocket.send(a.encode('utf-8'))
time.sleep(5)
a = '435742.,35.452,52434'
clientsocket.send(a.encode('utf-8'))
time.sleep(5)
clientsocket.close()
If you accept one single connection at a time (no need for a 1024 backlog then...) you can simply nest 2 loops: the outer one waiting for new connections the inner one processing input from the only one established connection. If you need to process more than one connection, you will have to use select or threads.
Here is an example for one single connection:
def clientsocketentry():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 8089))
serversocket.listen(5) # become a server socket, maximum 5 connectionn
cont = True
while cont:
connection, addr = serversocket.accept()
while True:
buf = connection.recv(64)
if len(buf) == 0: # end of connection
connection.close()
break
elif buf == b'killsrv': # request for closing server (beware of the byte string)
connection.close()
serversocket.close()
cont = False
break
else:
print (buf)
buf = buf.decode("utf-8")
buf = buf.split(',')
serverLong = buf[0]
print('Longitude:' + '' + serverLong)
serverLat = buf[1]
print('Lattitude:' + '' + serverLat)
serverAlt = buf[2]
print('Altitude:' + '' + serverAlt)
serverTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print('Time of Entry:' + ' ' + serverTime)
# connection.close() # wait for client to close
You are closing the socket at the end of your print logic in the ClientSocketEntry function.
serverTime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print('Time of Entry:' + ' ' + serverTime)
connection.close()
Instead of closing the connection there only close it when the user sends killsrv
Because every time you close the connection on the socket it is saying that you are expecting another client to connect to the server. So maybe before going into the while statement accept the connection and then pass it into the while statement, because the way you have it structured at the moment is expecting multiple connections from different clients.

Sending, receiving with python socket

I'm currently trying to write process that embeds a sequence of n IPs into packets and send it off to n server. Each server remove the outermost IP and then forward it to said IP. This is exactly like tunneling I know. During the process I also want the server to do a traceroute to where it's forwarding the packet and send that back to the previous server.
My code currently will forward the packets but it's stuck on performing the traceroute and getting it. I believe it's currently stuck in the while loop in the intermediate server. I think it's having something to do with me not closing the sockets properly. Any suggestion?
Client
#!/usr/bin/env python
import socket # Import socket module
import sys
import os
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 17353 # Reserve a port
FILE = raw_input("Enter filename: \n ")
NIP = raw_input("Enter Number of IPs: ")
accepted_IP = 0
IP= []
while accepted_IP < int(NIP):
IP.append(raw_input("Enter destination IP: \n"))
accepted_IP +=1
#cIP = raw_input("Enter intemediate IP: \n ")
ipv = raw_input("Enter IP version... 4/6")
try:
s.connect((host, port))
print "Connection sucessful!"
except socket.error as err:
print "Connection failed. Error: %s" %err
quit()
raw = open(FILE,"rb")
size = os.stat(FILE).st_size
ls = ""
buf = 0
for i in IP:
while len(i) < 15:
i += "$"
ls += i
header = ipv+NIP+ls+FILE
print ls
s.sendall(header + "\n")
print "Sent header"
data = raw.read(56) +ipv + NIP + ls
print "Begin sending file"
while buf <= size:
s.send(data)
print data
buf += 56
data = raw.read(56) + ipv + NIP + ls
raw.close()
print "Begin receiving traceroute"
with open("trace_log.txt","w") as tracert:
trace = s.recv(1024)
while trace:
treacert.write(trace)
if not trace: break
trace = s.recv(1024)
print "finished forwarding"
s.close()
Intermediate server
#!/usr/bin/env python
import socket
import subprocess
srvsock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
srvsock.bind( (socket.gethostname(), 17353) )
srvsock.listen( 5 ) # Begin listening with backlog of 5
# Run server
while True:
clisock, (remhost, remport) = srvsock.accept() #Accept connection
print
d = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
header = ""
while True:
b = clisock.recv(1)
if b == "\n":
break
header += b
num = 15 * int(header[1]) + 2
file_name = header[num:]
nheader = header[0]+ str(int(header[1])-1) + header[17:]
d.connect((socket.gethostname(), 12355))
d.sendall(nheader+'\n')
print "begin forwarding"
while True:
raw = clisock.recv(56 + num) # recieve data
ip = raw[-15:] # extract IP
ipv, NIP = raw[57] , str(int(raw[57])-1)
if NIP == "0":
while (raw):
print "stuck in this loop"
d.send(raw[:56])
raw=clisock.recv(56+num)
if not raw: break
else:
while (raw):
print raw[:57] + NIP + raw[59:-15]
print "\n"
d.send(raw[:57] + NIP + raw[59:-15])
raw = clisock.recv(56+num)
if not raw :break
print "Finish forwarding"
d.close()
break
print "Begin traceroute"
tracrt = subprocess.Popen(['traceroute','google.com'], stdout=subprocess.PIPE)
s.sendall(tracrt.communicate()[0])
print "Finished"
clisock.close()
s.close()
Destination server
import socket
s = socket.socket()
host = socket.gethostname()
port = 12355
s.bind((host,port))
s.listen(5)
while True:
csock, (client, cport) = s.accept()
print client
header = ""
while True:
b = csock.recv(1)
if b == "\n":
break
header += b
file_name = header[2:]
r = open("File_test_"+file_name,"wb")
print 'Opening file for writing'
while True:
print "Begin writing file" + " " + file_name
raw = csock.recv(56)
while (raw):
print raw
r.write(raw)
raw = csock.recv(56)
r.flush()
r.close()
print "finish writing"
break
print "closing connection"
csock.close()
s.close()
The intermediate server is stuck in clisock.recv() in this loop because the break condition not raw isn't met before the connection is closed by the client, and the client doesn't close the connection before receiving the traceroute from the intermediate server, so they are waiting on each other.
To remedy this, you might consider sending the file size to the intermediate server, so that it can be used to determine when the receive loop is done. Or, if your platform supports shutting down one half of the connection, you can use
s.shutdown(socket.SHUT_WR)
in the client after sending the file.

Python connect to IRC function - must be integer

I made a basic IRC bot that would join a certain channel and say a defined phrase, as part of learning Python. However, are there changes in the latest version of Python?
import socket
nick = 'TigerBot'
passdwd = '*****'
port = '6667'
net = 'irc.snoonet.org'
chan = '#WritingPrompts'
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Was ist da IRC Socket?
sock.connect ((net, port)) # Open server connection
irc.recv (4096) # Buffer setup
irc.send('nick ' + nick + '\r\n') # What is your name?
irc.send('USER AffixBot AffixBot AffixBot :Affix IRC\r\n') #Send User Info to the server
irc.send('JOIN ' + chan + '\r\n') # Join the pre defined channel
irc.send('PRIVMSG ' + chan + ' :Hello.\r\n') #Send a Message to the channel
while True: #While Connection is Active
data = irc.recv (4096) #Make Data the Receive Buffer
if data.find('PING') != -1: # If PING
irc.send('PONG ' + data.split()[1] + '\r\n') # Then PONG
Line 11 is the problem - apparently, what I've got down as a string needs to be an integer. How can I go about this?
Change your definition of port to be an integer.
port = 6667
not
port = '6667'
In general, if you have an existing string value that needs to be an int for a specific call, you can cast by calling int(str), which will return the value of str as an integer or raise a ValueError if it can't cast.

Categories