I am trying to build a TCP Chat Program that is multithreaded. So far I think most of the functions are setup fine. When starting the server and connecting with a client only responses sent from the server are broadcasted to all clients connected. I think I figured out why that is and it comes from the CONNECTION_LIST array I have. The server appends all clients to this list and I thought I had the same thing going for the clients but the client instance never sees this list so when sending messages they messages aren't sent anywhere. I basically need a way to copy the CONNECTION_list from the server instance over to the connected clients. I been trying figure out how to possibly do this all day and its driving me crazy.
import socket
import platform
import threading
import sys
import time
import os
'''Define Globals'''
HOST = ""
PORT = 25000
ADDR = (HOST, PORT)
CONNECTION_LIST = []
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
'''Connect Client to the Server'''
def client_connect():
server_ip = input("[+] Server's IP to connect to: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((server_ip, PORT))
print("[+] Connected to Server at address: %s" %client.getpeername()[0])
except ConnectionRefusedError:
print("[*] No Server Listening at Specified Address")
sys.exit()
communicate(client)
'''Threaded loop to continue listening for new connections'''
def server_loop():
server.bind(ADDR)
server.listen(10)
print("[*] Server started on %s" %platform.node())
while True:
client_socket, client_addr = server.accept()
CONNECTION_LIST.append(client_socket)
print("\r[+] New Connection from: %s" %client_addr[0])
'''Broadcast data to all clients except sender'''
def broadcast_data(sock, message):
for socket in CONNECTION_LIST:
if socket != server and socket != sock:
try:
socket.send(str.encode("[%s] => %s" %(os.getlogin(),message)))
except:
socket.close()
CONNECTION_LIST.remove(socket)
'''Server Host Connect Back'''
def self_connect():
sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sc.connect(("localhost", 25000))
CONNECTION_LIST.append(sc)
communicate(sc)
def communicate(client):
dump_thread = threading.Thread(target=dump, args=(client,))
dump_thread.start()
while True:
try:
time.sleep(0.5)
data = input("> ")
broadcast_data(client, data)
except:
print("[*] Error - Program Terminating")
client.close()
sys.exit()
def dump(client):
while True:
print(client.recv(1024).decode("utf-8"))
def main():
server_thread = threading.Thread(target=server_loop)
while True:
try:
print("Select Operating Mode")
print("---------------------")
print("1. Server Mode")
print("2. Client Mode")
mode = int(input("Enter mode of operation: "))
print("\n\n")
if mode in [1,2]:
break
else:
raise ValueError
except ValueError:
print("Enter either (1) for Server or (2) for Client")
if mode == 1:
server_thread.start()
time.sleep(1)
self_connect()
elif mode == 2:
client_connect()
main()
Related
I have put together a server and client code to use in a messaging app. When I run the server and starts one client, everything works fine. When I start a second client, I can send messages from the first client and the second client will recieve them. I can send one message from the second client and the first client will recieve this first message. But after this message, the second client can not send or the server can not receive the data for some reason. The first client can still send messages.
I dont know where the mistake is, but I believe either the client can not .send() or the server can not .recv().
(I am quite new to programming so the code might be quite messy and not the most understandeble, and maybe there are several flaws...)
The server code
import socket
from _thread import *
import sys
HOST = "127.0.0.1"
PORT = 12000
client_socket = set()
def threaded(conn):
while True:
try:
data = conn.recv(1024).decode()
if not data:
print("Lost connection")
break
for conn in client_socket :
conn.send(data.encode())
except:
break
print("Gone")
conn.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
print("Server is up and running")
while True:
conn, addr = s.accept()
print("Connected to", addr)
client_socket .add(conn)
start_new_thread(threaded, (conn, ))
The client code
import threading
import socket, sys
HOST = "127.0.0.1"
PORT = 12000
check= ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
def background():
while True:
answer= s.recv(1024).decode()
if check!= answer and answer!= "":
print(answer)
threading1 = threading.Thread(target=background)
threading1.daemon = True
threading1.start()
while True:
message= input()
if message!= "":
s.send(message.encode())
check = message
I am trying to test connections to a server from a network. I have 2 seperate files; server.py and network.py.
My server.py works as it says "Server Started" but when I try to run network.py to connect to the server, it does not let me run it. I am doing this in VSCode so I don't know if its a software bug.
I have provided the server.py code and network.py code (They are in the same workspace and directory) and for privacy I have hidden my IP address
Server.py:
import socket
from _thread import *
import sys
server = "XXXXXX" # server address on LAN
port = 5555 # 5555 is an open safe port for use
socket_x = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# .AF_INET allows sokcet to communicate with addresses
# SOCK_STREAM IS USED BY TCP SERVER WHICH ALLOWS DEVICES TO TRANSMIT DATA TO ONE ANOTHER
try: # check for socket errors
socket_x.bind((server, port)) # creating server
except socket.error as e:
str(e)
socket_x.listen(2) # allows for connections (2 people can connect)
print("Waiting for Connection, Test Server Started")
def threaded_client(conn):
conn.send(str.encode("Connected"))
reply = ""
while True:
try:
data = conn.recv(2048)
reply = data.decode("utf-8")
if not data:
print("Disconnected")
break
else: # if there is data
print("Recieved: ", reply)
print("Sending: ", reply)
conn.sendall(str.encode(reply))
except:
break
print("Lost connection")
conn.close()
while True: # continuosly looking for connections
conn, address = socket_x.accept() # accept any incoming connections and store into variables
print("Connected to:", address)
# start_new_thread(threaded_client, (conn, ))
start_new_thread(threaded_client, (conn, ))
Network.py:
import socket
class Network:
def __init__(self):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server = "XXXXXX" # will always be the same
self.port = 5555
self.address = (self.server, self.port)
self.id = self.connect()
print(self.id)
def connect(self):
try: # trying to connect
self.client.connect(self.address)
return self.client.recv(2048).decode()
except:
pass
n = Network()
Thank you for the help
I'm trying to send console commands from one machine to another using Python sockets. I want the server to send back the results of the command to the client. If the client types "ls" I want the server to send back the results of running that command. Instead of the expected result, the server just says "action completed: ls". How can I fix this so the server will run the expect commands and return the result?
Server:
import socket
from subprocess import call
def main():
host = '127.0.0.1'
port = 5000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
print('Connection established: ' + str(addr))
while True:
try:
data = c.recv(1024).decode('utf-8')
print('sending data: ' + data)
c.send(data.encode('utf-8'))
if data == 'q':
break
except NameError:
error = 'Command does not exist'
c.send(error.encode('utf-8'))
continue
except SyntaxError:
error = 'Command does not exist'
c.send(error.encode('utf-8'))
continue
c.close()
Client:
import socket
from subprocess import call
def main():
host = '127.0.0.1'
port = 5000
s = socket.socket()
s.connect((host, port))
message = str(input('> '))
while message != 'q':
try:
s.send(message.encode('utf-8'))
data = s.recv(1024).decode('utf-8')
print('Action completed: %s' % data)
message = str(input('> '))
except NameError:
print("Command not recognized.")
continue
except SyntaxError:
print("Command not recognized")
continue
I recently built a socket connection in order to communicate with an android device.
I decided to use UDP instead of TCP (which is what you did). For UDP as well as TCP you need a sender and a receiver on both sides of the communication.
The port number that is received in the "addr" variable changes with every connection, so you cannot use it.
What I did, I assigned two different ports one for sending from A to B and the other port to send from B to A.
Here is my server code:
import socket # socket connection
import threading # Multithreading
import time # Timeing
# ----------------------------------------------
# Variables
# ----------------------------------------------
UDPListen2Port = 12345
UDPSend2Port = 123456
Listen2IP = '' # input your local IP here
# ----------------------------------------------
# Threading class
# ----------------------------------------------
class signalProcessingThread(threading.Thread):
def __init__(self, iP, cmdIn):
threading.Thread.__init__(self)
self.iP = iP
self.cmdIn = cmdIn
def run(self):
print("Recv--", self.iP ,"--", self.cmdIn) # Display Thread Info
cmdOut = self.EvalMessage() # Actual signal processing
byteOut = bytes(cmdOut.encode("utf-8")) # Convert Server reply to bytes
sock.sendto(byteOut,(self.iP,UDPSend2Port)) # Send Server Reply to Socket
# ----------------------------------------------
# Initialize Socket
# ----------------------------------------------
sock = socket(AF_INET, SOCK_DGRAM) # -- UDP -- connection
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # in case the port was not properly closed before
sock.bind((Listen2IP,UDPListen2Port)) # bind to the port
# ----------------------------------------------
# Listen to Socket
# ----------------------------------------------
while True:
try: # wait for a connection
data,addr = sock.recvfrom(66507) # number of bytes in the message
msg = data.decode('utf-8')
newThread = signalProcessingThread(addr[0],msg)
newThread.start()
except KeyboardInterrupt:
print('Connection failed')
sock.close()
sock.close()
The client code is quite similar, with the difference that it doesn't necessarily need to run in a thread. Hope I could help.
I'm creating a client to server based chat client and every time I setup a server and a client, the server keeps listening for a connection and when the client attempts to connect this error appears [WinError 10054] An existing connection was forcibly closed by the remote host, however the server still listens for a connection. I'm using python version 3.6.1
Script
import socket
import threading
clients = []
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
mode = input("Enter 1 for server mode and enter 2 for client mode")
if mode == "1":
def get_ip():
try:
stest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
stest.connect(('10.255.255.255', 1))
IP = stest.getsockname()[0]
except:
IP = '127.0.0.1'
finally:
stest.close()
return IP
print("IP: " + get_ip())
s.bind((get_ip(), 7999))
s.setblocking(0)
print("Waiting for connection")
while True:
try:
data, addr = s.recvfrom(1024)
if data.decode() == "Quit":
quitmsg = str(addr) + " has quit the chat."
clients.remove(addr)
for client in clients:
s.sendto(quitmsg.encode("utf-8"), client)
break
elif data:
print(data)
if addr not in clients:
clients.append(addr)
print(clients[0])
for client in clients:
print(client)
s.sendto(data, client)
except:
pass
s.close()
elif mode == "2":
while True:
try:
ip = input("Enter in an ip address")
socket.inet_aton(ip)
except socket.error:
print("Invalid IPv4 address")
continue
while True:
try:
port = int(input("Enter in port number"))
except ValueError:
print("Invalid Port Number")
continue
break
addr = (ip, port)
break
s.connect(addr)
def recvmsg():
while True:
data = s.recv(1024)
print(data)
if data:
print(data.decode())
recv = threading.Thread(name="recvmsg", target=recvmsg)
recv.daemon = True
recv.start()
while True:
string = input(">>")
s.send(string.encode("utf-8"))
if str(string) == "Quit":
break
s.close()
print("Disconnected from chat")
Server Waiting For connection even after client can't connect
Client Failed to connect
If your server is not on the local network, make sure port 7999 is open and forwarded on its access point. Otherwise the packets will just be dropped by the router. If it is on your local network, still try forwarding. Also according to https://www.speedguide.net/port.php?port=7999 the port has been used by a worm, so maybe permanently closed on the other network?? Unlikely but possible.
How do I make a simple Python echo server that remembers clients and doesn't create a new socket for each request? Must be able to support concurrent access. I want to be able to connect once and continually send and receive data using this client or similar:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = raw_input("Server hostname or ip? ")
port = input("Server port? ")
sock.connect((host,port))
while True:
data = raw_input("message: ")
sock.send(data)
print "response: ", sock.recv(1024)
I.e. with the server running on port 50000, using the above client I want to be able to do this:
me#mine:~$ client.py
Server hostname or ip? localhost
Server Port? 50000
message: testa
response: testa
message: testb
response: testb
message: testc
response: testc
You can use a thread per client to avoid the blocking client.recv() then use the main thread just for listening for new clients. When one connects, the main thread creates a new thread that just listens to the new client and ends when it doesn't talk for 60 seconds.
import socket
import threading
class ThreadedServer(object):
def __init__(self, host, port):
self.host = host
self.port = port
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)
while True:
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
if __name__ == "__main__":
while True:
port_num = input("Port? ")
try:
port_num = int(port_num)
break
except ValueError:
pass
ThreadedServer('',port_num).listen()
Clients timeout after 60 seconds of inactivity and must reconnect. See the line client.settimeout(60) in the function ThreadedServer.listen()