Why I do not caught socket timeout? - python

I do not understand, why in this code below I do not have the timeout (even if I set it with settimeout, I cant see the exception caught):
import socket
HOST = 'x.x.x.x'
open_ports = []
closed_ports = []
def scan(PORT):
sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#sock_tcp.settimeout(0.5)
SERVER_ADDR = (HOST, PORT)
try:
portStatusTCP = sock_tcp.connect_ex(SERVER_ADDR)
if portStatusTCP==0:
open_ports.append(PORT)
print(str(PORT)+' is OPEN')
else:
closed_ports.append(PORT)
print(str(PORT)+' is CLOSED')
except socket.error as socketerror:
print("ERROR"+socketerror)
sock_tcp.close()
for PORT in range(15,25):
print('scanning port: '+str(PORT))
scan(PORT)
print(open_ports)
print(closed_ports)

Related

(Python) Socket Chat returning usernames as IP and Port

I'm working on a TCP socket chat assignment for school. I'm having trouble getting the last part done, which is returning all usernames to the client when it asks for it. The client can write /users to get all connected users usernames, but instead gets the IP and PORT they are connected to, output example:
('127.0.0.1', 54612)
Server Code:
import socket, threading
clients = []
nicknames = []
BYTES = 1024
FORMAT = "utf-8"
def server():
IP = "127.0.0.1"
PORT = 9090
BIND = (IP, PORT)
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(BIND)
sock.listen()
print("Welcome to Budget-Discord!")
while True:
client, addr = sock.accept()
print("Connected with {}".format(str(addr)))
client.send('NICKNAME'.encode(FORMAT))
nickname = client.recv(BYTES).decode()
nicknames.append(nickname)
clients.append(client)
print("Nickname is {}".format(nickname))
print(nicknames)
#broadcast("{} joined!".format(nickname).encode(FORMAT))
client.send("\t >>> Connected to server!".encode(FORMAT))
threading.Thread(target=user_conn, args=[client, addr]).start()
except Exception as e:
print(f"Error, socket: {e}")
def sendall(msg: str, conn: socket.socket): # Broadcast
for client_conn in clients:
if client_conn != conn:
try:
client_conn.send(msg.encode())
except Exception as e:
print(f"Error, sendall: {e}")
byeee(client_conn)
def user_conn(conn: socket.socket, nicknames):
while True:
try:
msg = conn.recv(BYTES).decode()
if "/users" in msg:
conn.sendall(bytearray(str(nicknames).encode()))
if msg:
print(msg)
allchat = f"{msg}"
sendall(allchat, conn)
# else:
# pass
except Exception as e:
print(f"Error, user connection: {e}")
byeee(conn)
break
def byeee(conn: socket.socket):
if conn in clients:
conn.close()
clients.remove(conn)
if __name__ == "__main__":
server()
Client Code:
import socket, threading
IP = "127.0.0.1"
PORT = 9090
BIND = (IP, PORT)
BYTES = 1024
FORMAT = "utf-8"
nickname = input("Choose your nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(BIND)
def receive():
while True:
try:
msg = client.recv(BYTES).decode()
if msg == 'NICKNAME':
client.send(nickname.encode())
# elif message == "/users"
else:
print(msg)
except Exception as e:
print(f"Error, client receive: {e}")
client.close()
break
def write():
while True:
msg = f"{nickname}: {input('')}"
client.send(msg.encode())
receive_t = threading.Thread(target=receive).start()
write_t = threading.Thread(target=write).start()
I have tried different things, got tuple errors for the most part so I converted the /users in the server module to bytearray...
In the function server, this line is sending addr as the second argument:
threading.Thread(target=user_conn, args=[client, addr]).start()
but the function user_conn has a second argument of nicknames:
def user_conn(conn: socket.socket, nicknames):
so send nicknames instead in server:
threading.Thread(target=user_conn, args=[client, nicknames]).start()

How to limit number of connections to server socket

I'm trying to have multiple clients connect to a server socket and transfer data between them, however I want to limit the number of connections that can be made to the server/ number of client processes to 3. How can I do this?
server:
import socket
from _thread import *
PORT = 5050
HOST = socket.gethostbyname(socket.gethostname())
ADDR = (HOST, PORT)
ThreadCount = 0
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
tcp.bind(ADDR)
except socket.error as e:
print(str(e))
print("Awaiting connection")
tcp.listen(5)
def threaded_client(connection):
connection.send(str.encode('Welcome to sv'))
while True:
data = connection.recv(2048)
reply = 'Server returns: ' + data.decode('utf-8')
if not data:
break
connection.sendall(str.encode(reply))
connection.close()
while True:
Client, address = tcp.accept()
print('Connected to: ' + address[0] + ':' + str(address[1]))
start_new_thread(threaded_client, (Client, ))
ThreadCount += 1
print('Number of threads: ' + str(ThreadCount))
ServerSocket.close()
client:
import socket
Client = socket.socket(socket.AF_INET, socket. SOCK_STREAM)
PORT = 5050
HOST = socket.gethostbyname(socket.gethostname())
ADDR = (HOST, PORT)
print('Awaiting connection')
try:
Client.connect(ADDR)
except socket.error as e:
print(str(e))
Response = Client.recv(1024)
while True:
Input = input('Sends Info: ')
Client.send(str.encode(Input))
Response = Client.recv(1024)
print(Response.decode('utf-8'))
Cliente.close()

How can I receive multiple messages from one connection?

I have a server and I need it to receive multiple connections and messages.
The server receives new connections without problems but it doesn't get multiple messages from one connection.
import socket
import select
HEADER_LENGTH = 1024
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
server_socket.bind((HOST, PORT))
except socket.error as e:
print(str(e))
print("Server is connected")
server_socket.listen(5)
sockets_list = [server_socket]
clients = {}
print("Server is listening")
def receive_message(conn):
try:
data = conn.recv(HEADER_LENGTH)
if not len(data):
return False
strdata = data.decode('utf-8')
print(strdata)
return strdata
except Exception as e:
print(e)
return False
def handle_client():
conn, addr = server_socket.accept()
print(f"Accepted new connection from {addr[0]}:{addr[1]}")
sockets_list.append(conn)
while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], [], 0)
for i in read_sockets:
if i == server_socket:
handle_client()
else:
print("received message")
message = receive_message(i)
if message is False:
sockets_list.remove(i)
try:
del clients[i]
except KeyError:
pass
continue
if message is not None:
clients[i] = message
if message is not None:
for client_socket in clients:
if client_socket != i:
client_socket.send(str.encode(message))
print("sent to all players")
What happens it that after receiving the first message, the server stops receiving messages from that connection.
And of course there is a lot more code but I showed you the relevant code.
I'll be very happy if someone helps me with that, I've surfed the web so much but haven't seen a solution for my problem.
updates:
I've tried to put socket.close() on my client side(written in Java) and then server gets maximum 2 messages and the problems with it are:
1. The server gets maximum 2 messages.
2. the connection changes(I need that the connection will stay static if possible)
try this code block
#-*- coding:utf-8 -*-
import socket
import sys
#get machine ip address
server_ip = socket.gethostbyname(socket.gethostname())
#create socket object
s = socket.socket()
#define port number
port = 6666
#bind ip and port to server
s.bind((server_ip,port))
#now waiting for clinet to connect
s.listen(5)
print("Enter this ip to connect your clinet")
print(server_ip)
clients = []
flag = True
recv_data = ""
if not clients:
c, addr = s.accept()
print("this is c ",c," this is Addr ",addr)
clients.append(c)
recv_data = c.recv(1024)
print(recv_data.decode("utf-8"))
if flag == True:
while recv_data.decode("utf-8") != "EX":
recv_data = c.recv(1024)
recv_data.decode("utf-8")
if recv_data.decode("utf-8") == "EX":
s.close()
print("check false")
break
s.close()

How to send data to client with conn.send()

Im trying to create a simple chat server. I've been able to send information to the server through the client using 'client.send()' but I cannot seem to do the same server->client
I have tried using methods such as conn.send() and conn.sendall(), but (I guess since the code is in a try) they seem to get skipped after the initial conn.send(str.encode("Connected"))
Server code
import socket
from _thread import *
import sys
server = "192.168.0.4"
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((server, port))
except socket.error as e:
str(e)
s.listen(2)
print("Waiting for a connection, Server Started")
def threaded_client(conn):
conn.send(str.encode("Connected"))
reply = ""
while True:
conn.send(str.encode(str(reply)))
try:
data = conn.recv(2048*1)
reply = data.decode("utf-8")
if not data:
print("Disconnected")
break
else:
print("Received: ", reply)
print("Sending : ", reply)
conn.sendall(str.encode(reply)) #Where I want to send information to the client
except:
break
print("Lost connection")
conn.close()
while True:
conn, addr = s.accept()
print("Connected to:", addr)
start_new_thread(threaded_client, (conn,))
client code
import socket
class Network:
def __init__(self):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server = "192.168.0.4"
self.port = 5555
self.addr = (self.server, self.port)
self.id = self.connect()
print(self.id)
def connect(self):
try:
self.client.connect(self.addr)
return self.client.recv(2048).decode()
except:
pass
def send(self, data):
try:
self.client.send(str.encode(data))
return self.client.recv(2048).decode()
except socket.error as e:
print(e)
from network import Network
n = Network()
while True:
n.send("sending stuff") #this works/sends properly
You forgot to use print() to display data from server
while True:
print( n.send("sending stuff") )
BTW: in server you send the same data two times - with conn.send() and conn.sendall()

Python Tcp disconnect detection

I have a simpletcp example:
import socket
import time
TCP_IP = '127.0.0.1'
TCP_PORT = 81
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
while True:
s.send(bytes('hello', 'UTF-8'))
time.sleep(1)
s.close()
How can I detect, if I lost the connection to the server, and how can I safely reconnect then?
Is it necessary to wait for answer to the server?
UPDATE:
import socket
import time
TCP_IP = '127.0.0.1'
TCP_PORT = 81
BUFFER_SIZE = 1024
def reconnect():
toBreak = False
while True:
s.close()
try:
s.connect((TCP_IP, TCP_PORT))
toBreak = True
except:
print ("except")
if toBreak:
break
time.sleep(1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
while True:
try:
s.send(bytes('hello', 'UTF-8'))
print ("sent hello")
except socket.error as e:
reconnect()
time.sleep(1)
s.close()
If I break the connection, it raises an error (does not really matter what), and goes to the
reconnect loop. But after I restore the connection, the connect gives back this error:
OSError: [WinError 10038] An operation was attempted on something that is not a socket
If I restart the script, which calls the same s.connect((TCP_IP, TCP_PORT)), it works fine.
You'll get a socket.error:[Errno 104] Connection reset by peer exception (aka ECONNRESET) on any call to send() or recv() if the connection has been lost or disconnected. So to detect that, just catch that exception:
while True:
try:
s.send(bytes('hello', 'UTF-8'))
except socket.error, e:
if e.errno == errno.ECONNRESET:
# Handle disconnection -- close & reopen socket etc.
else:
# Other error, re-raise
raise
time.sleep(1)
Use a new socket when you attempt to reconnect.
def connect():
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
return s.makefile('w')
except socket.error as e:
log("socket error {} reconnecting".format(e))
time.sleep(5)
dest = connect()
while True:
line = p.stdout.readline()
try:
dest.write(line)
dest.flush()
except socket.error as e:
log("socket error {} reconnecting".format(e))
dest = connect()
Can you try that (I think that you does'not try socket.SO_REUSEADDR):
def open_connection():
data0=''
try:
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Connect the socket to the port where the server is listening
server_address = ('192.168.0.100', 8000)
sock.settimeout(10) # TimeOut 5 secunde
while True:
try:
sock.connect(server_address)
message = 'new connection'
sock.sendall(message)
# Look for the response
amount_received = 0
data0=sock.recv(1024)
amount_received = len(data0)
return
finally:
wNET = 0
pass
except:
sock.close()
time.sleep(60)
del data0
This is the code based on thread. The main tip is that the received buffer cannot be none, if the socket is connected.
import time
import socket
import threading
def connect():
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.settimeout(60)
return s
except socket.error as e:
print("socket error {} reconnecting".format(e))
time.sleep(5)
soc = connect()
def runSocket():
global soc
while True:
try:
recBuf = soc.recv(64)
if recBuf == b'': #remote server disconnect
soc = connect()
else:
print(recBuf)
except socket.timeout:
print("Timeout")
except Exception as e:
print("other socket error {}".format(e))
soc = connect()
socketThread = threading.Thread(target=runSocket)
socketThread.start()

Categories