My Python socket chat with multithreading only accepts one connection. If I try to connect a second client it doesn't work. On the client side it seems like everything is okay but if i try to send a second message from client 2 the message doesn't arrive.
import socket
import threading
class TxtSocket:
def __init__(self, host="127.0.0.1" , port=5555):
self.host = host
self.port = port
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.bind((self.host, self.port))
print("Socket was created")
def server(self):
self.s.listen()
print("Server is listening")
conn, addr = self.s.accept()
print(f"{addr} is now connected.")
while True:
data = conn.recv(1024).decode("utf8")
print(data)
if not data:
break
if __name__ == "__main__":
txtsocket = TxtSocket()
for i in range(0, 26):
t = threading.Thread(target=txtsocket.server())
t.start()
# Client
import socket
def Text():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 5555))
print("Connected")
while True:
message = input("Deine Nachricht: ")
message = message.encode("utf8")
s.send(message)
Text()
Need couple mods to the server to handle multiple clients.
Need main loop to keep accepting new connections and forking off the processing to a thread
Create a new thread to handle client connection when socket gets a new connection.
The following server code works with multiple running clients as specified above.
# server
import socket
import threading
class TxtSocket:
def __init__(self, host="127.0.0.1", port=5555):
self.host = host
self.port = port
self.thread = 0
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.bind((self.host, self.port))
print("Socket was created")
def handle(self, conn, addr):
self.thread += 1
print(f"Thread-{self.thread} {addr} is now connected")
while True:
data = conn.recv(1024)
if not data:
break
print(data.decode("utf8"))
conn.close()
def server(self):
# specify the number of unaccepted connections that the server
# will allow before refusing new connections.
self.s.listen(5)
print(f'Server listening on tcp:{self.host}:{self.port}')
while True:
conn, addr = self.s.accept()
# create new thread to handle the client connection
t = threading.Thread(target=self.handle, args=(conn, addr))
t.start()
if __name__ == "__main__":
txtsocket = TxtSocket()
txtsocket.server()
Note that Python has a SocketServer module that can make some of this easier with a TCPServer that does much of the work. See server example.
you can use thread for close other connections
import socket
from _thread import start_new_thread
server = socket...
first_connection = None
def check_con_isalive():
try:
while True:
first_connection.send(b"\0")
except Exception:
print("connnection was closed")
first_connection.close()
def thread_con(con):
global first_connection
if not first_connection:
first_connection = con
start_new_thread(check_con_isalive, ())
...
else:
print("blocking new connections")
con.close()
if __name__ == '__main__':
while True:
con, adr = server.accept()
start_new_thread(thread_con, (con, ))
Related
I am setting up a client/server in Python with the ability to handle multiple clients.
Server code:
import socket
import threading
class Server:
def __init__(self):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(('127.0.0.1',1234 ))
print("Waiting for connection")
self.server.listen()
self.loop()
def thread_client(self, conn, addr):
print(addr, ' has connected')
while True:
data = conn.recv(1024)
conn.sendall(data)
def loop(self):
while True:
conn, addr = self.server.accept()
x = threading.Thread(target = self.thread_client, args=(conn, addr,))
x.start()
self.server.close()
s = Server()
Client code:
import socket
class Client:
def __init__(self):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect()
def connect(self):
try:
self.client.connect(('127.0.0.1', 1234))
except:
print("Something went wrong...")
def send(self, data):
self.client.sendall(data)
return self.client.recv(1024)
c = Client()
print(c.send(b'Hello World'))
print(c.send(b'Hello World'))
When I run py server.py in one terminal this is all I get:
And from the client terminal this is how it looks:
My question is, why am I not recieving a simple print message from the initialization of the server? What does CLOSE_WAIT and FIN_WAIT_2 mean when I run netstat?
The server thread will loop forever until the socket times out resulting in WAIT states on the created sockets as shown in netstat command. Add a check in the server thread to check when data from the client is complete.
Socket Programming HOWTO states:
When a socket.recv returns 0 bytes, it means the other side has closed
(or is in the process of closing) the connection. You will not receive any
more data on this connection.
Server update:
import socket
import threading
class Server:
def __init__(self):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(('127.0.0.1', 1234))
print("Waiting for connection")
self.server.listen()
self.loop()
def loop(self):
while True:
conn, addr = self.server.accept()
x = threading.Thread(target=Server.thread_client, args=(conn, addr,))
x.start()
self.server.close()
#staticmethod
def thread_client(conn, addr):
print(addr, ' has connected')
while True:
data = conn.recv(1024)
if len(data) == 0:
break
print("recv:", data)
conn.sendall(data)
conn.close()
s = Server()
For the client, close the socket connect when done.
Client update:
c = Client()
print(c.send(b'Hello World'))
print(c.send(b'Hello World'))
c.client.close() # added
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
below is a basic program that has the client enter a name, then it connects to the server and gets a response, and the server then appends the name to a list, the problem is when a second client connects to the server the first client loses connection and this happens for every client that connects. how do I solve this?
server.py :
import socket
s = socket.socket()
host = "127.0.0.1"
port = 5409
s.bind((host, port))
names = []
while True:
s.listen(5)
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
while True:
try:
name = c.recv(1024)
print name
except:
print ""
if name not in names:
names.append(name)
message = "Hello " + name
c.sendall(message)
print names
break
client.py :
import socket # Import socket module
s = socket.socket() # Create a socket object
host = "127.0.0.1" # Get local machine name
port = 5409 # Reserve a port for your service.
name = raw_input("What Is your Name? ")
s.connect((host, port))
while True:
try:
s.send(name)
except:
break
try:
print s.recv(1024)
except:
break
You will need to make your server able to handle concurrent connections, either with multithreading, multiprocessing, or select.
The socketserver module provides convenient basic server classes using threading or multiprocessing. The official documentation has some good examples. Here is one using the threading module for concurrency:
import socket
import threading
import socketserver
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def client(ip, port, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((ip, port))
sock.sendall(bytes(message, 'ascii'))
response = str(sock.recv(1024), 'ascii')
print("Received: {}".format(response))
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
HOST, PORT = "localhost", 0
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
ip, port = server.server_address
# Start a thread with the server -- that thread will then start one
# more thread for each request
server_thread = threading.Thread(target=server.serve_forever)
# Exit the server thread when the main thread terminates
server_thread.daemon = True
server_thread.start()
print("Server loop running in thread:", server_thread.name)
client(ip, port, "Hello World 1")
client(ip, port, "Hello World 2")
client(ip, port, "Hello World 3")
server.shutdown()
server.server_close()
If you would like to build your own server without using socketserver, you can look at the source for the socketserver module (it's simple), or there are plenty of examples online of basic TCP/UDP servers using all three concurrency methods.
I'm trying to create a simple chat application using sockets in Python (with threads). Application is simple client has to threads one to send data and another to receive. Server has to two threads one to accept client connection and another to broadcast the message. But on running the below code, I'm getting error message
Transport endpoint is not connected
Can anybody tell me why I'm getting this error
Client
import socket, threading
def send():
msg = raw_input('Me > ')
cli_sock.send(msg)
def receive():
data = cli_sock.recv(4096)
print('> '+ str(data))
if __name__ == "__main__":
# socket
cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# connect
HOST = 'localhost'
PORT = 5028
cli_sock.connect((HOST, PORT))
print('Connected to remote host...')
thread_send = threading.Thread(target = send)
thread_send.start()
thread_receive = threading.Thread(target = receive)
thread_receive.start()
Server
import socket, threading
def accept_client():
while True:
#accept
cli_sock, cli_add = ser_sock.accept()
CONNECTION_LIST.append(cli_sock)
print('Client (%s, %s) connected' % cli_add)
def broadcast_data():
while True:
data = ser_sock.recv(4096)
for csock in CONNECTION_LIST:
try:
csock.send(data)
except Exception as x:
print(x.message)
cli_sock.close()
CONNECTION_LIST.remove(cli_sock)
if __name__ == "__main__":
CONNECTION_LIST = []
# socket
ser_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# bind
HOST = 'localhost'
PORT = 5028
ser_sock.bind((HOST, PORT))
# listen
ser_sock.listen(1)
print('Chat server started on port : ' + str(PORT))
thread_ac = threading.Thread(target = accept_client)
thread_ac.start()
thread_bd = threading.Thread(target = broadcast_data)
thread_bd.start()
You're using server sockets incorrectly. You cannot recv on server sockets, instead you accept connections on them; accept returns the actual connection socket:
ser_sock.listen(1)
sock, addr = ser_sock.accept()
print('Got connection from {}'.format(addr))
# only this *connection* socket can receive!
data = sock.recv(4096)
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()