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
Related
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, ))
I'm currently following this tutorial on how to make a multiplayer game using python: https://www.youtube.com/watch?v=McoDjOCb2Zo
I'm currently trying to connect to a server file with a network file. Running the server file prints out the correct piece of information but once I try connecting to it with the network file nothing happens.
Here is my server code. When it runs it prints out "Waiting for a connection, Server started
(I have removed my IP address, but I know that I have the right one in for when I run my code)
import socket
from _thread import *
server = "***.***.*.**"
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("Waitng for a connection, Server Started")
def threaded_client(conn):
conn.send(str.encode("Connected"))
reply = ""
while True:
try:
data = conn.recieve(2048)
reply = data.decode("utf-8")
if not data:
print("Disconnected")
break
else:
print("Received", reply)
print("Sending: ", reply)
conn.sendall(str.encode(reply))
except:
break
print("Lost Connection")
conn.close()
while True:
conn, addr = s.accept()
print("Conneced to: ", addr)
start_new_thread(threaded_client, (conn,))
And here is the code for my network
import socket
class Network:
def __init__(self):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server = "***.***.*.**"
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
n = Network()
When I run this code after initializing the server, it is supposed to print out "Connected"
I'm trying to achieve interprocess communication with socket. I have this code which acts as a socket server. When a message is received, the server broadcasts all the message to the other conntected clients.
from socket import AF_INET, gethostname, socket, SOCK_STREAM
import _thread as thread
clients = []
HOST = gethostname()
PORT = 33000
BUFFER_SIZE = 1024
ADDR = (HOST, PORT)
s = socket(AF_INET, SOCK_STREAM)
s.bind(ADDR)
def accept_client():
while True:
client, _ = s.accept()
clients.append(client)
print("Client accepted.")
thread.start_new_thread(handle_client, (client, ))
def handle_client(client):
while True:
message = client.recv(BUFFER_SIZE)
print("Incoming message: {}".format(message.decode('utf-8')))
broadcast(message)
def broadcast(message):
print("Broadcasting...")
for c in clients:
print("Broadcasting to {}".format(c))
c.send(message)
if __name__ == '__main__':
s.listen()
print("Listening...")
thread.start_new_thread(accept_client, ())
try:
while True:
pass
except KeyboardInterrupt:
print("Exited.")
exit(0)
And here is a class for my client.
from socket import AF_INET, gethostname, socket, SOCK_STREAM
import _thread as thread
class SocketClient:
buffer_size = 1024
def __init__(self, host=gethostname(), port=33000):
self.host = host
self.port = port
self.buffer_size = 1024
self.s = socket(AF_INET, SOCK_STREAM)
self.s.connect((self.host, self.port))
def bind_callback(self, callback, args=()):
thread.start_new_thread(self.receive, (callback, args))
def receive(self, callback, args):
while True:
try:
msg = self.s.recv(self.buffer_size).decode('utf-8')
callback(msg, *args)
except OSError as err:
self.close()
raise err
except NameError:
raise err
def send(self, msg):
try:
self.s.send(msg.encode('utf-8'))
except:
self.close()
def close(self):
self.send('{clientClose}')
self.s.close()
In other script which I've create the object ofSocketClient, there is an infinite amount of incoming socket after the script terminates (by Ctrl+D in Python). The server script (which prints an attempt when an incoming socket is received) shows this repeatedly:
Incoming message:
Broadcasting...
Broadcasting to <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.1.1', 33000), raddr=('127.0.0.1', 44126)>
Broadcasting to <socket.socket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.1.1', 33000), raddr=('127.0.0.1', 44276)>
Observe that there appears to be no incoming messages.
My assumption is that I've failed to close the socket connection properly (before exiting). How can this be achieved? Thank you in advance.
Calling client.recv(1024) will block and return 1 to 1024 bytes unless the client disconnects, in which case it will return an empty bytestring:
def handle_client(client):
while True:
message = client.recv(BUFFER_SIZE)
if not message:
# client disconnected
break
...
I need to write a simple program (no thread allowed) using Python for a
simple request/response stateless server. client
sends a request and server responds with a response. Also it needs to handle multiple transaction
This is the simple one I am using:
import asyncore, socket
class Server(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.bind(('', port))
self.listen(1)
def handle_accept(self):
# when we get a client connection start a dispatcher for that
# client
socket, address = self.accept()
print 'June, Connection by', address
EchoHandler(socket)
class EchoHandler(asyncore.dispatcher_with_send):
# dispatcher_with_send extends the basic dispatcher to have an output
# buffer that it writes whenever there's content
def handle_read(self):
self.out_buffer = self.recv(1024)
if not self.out_buffer:
self.close()
s = Server('', 5088)
syncore.loop(timeout=1, count=10)
import asyncore, socket
class Client(asyncore.dispatcher_with_send):
def __init__(self, host, port, message):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((host, port))
self.out_buffer = message
def handle_close(self):
self.close()
def handle_read(self):
print 'June Received', self.recv(1024)
self.close()
c = Client('', 5088, 'Hello, world')
asyncore.loop(1)
Pythons native socket library supports timeouts out of the box:
socket.settimeout(value)
So something like this should work:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("127.0.0.1", 12345))
sock.listen(1)
conn, addr = s.accept()
conn.settimeout(10)
A bit more high level: https://docs.python.org/2/library/socketserver.html and https://docs.python.org/2/library/socketserver.html#socketserver-tcpserver-example
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()