Python socket wait for client connection - python

Is there a way to stop the while loop until the clients connect to this server?
The server shuld create a new thread for each new client connection, it is possible?
import socket
import threading
def clientdialog(myS):
conn, addr = myS.accept()
print ("Connection from: " + str(addr))
while 1:
data = conn.recv(1024).decode("utf-8")
if not data or data == 'q':
break
print ("from connected user: " + str(data))
host = "192.168.1.3"
port = 1998
mySocket = socket.socket()
mySocket.bind((host,port))
while True:
mySocket.listen(10)
#whait until socket don't connect
try:
threading._start_new_thread(clientdialog, (mySocket))
except:
print("error starting thread")

The socket.listen function is to be called once, because it sets the size of the connection queue.
Another function called socket.accept will block until connections are made. Modify your code like this:
mySocket = socket.socket()
mySocket.bind((host,port))
mySocket.listen(10)
while True:
client_socket, client_address = mySocket.accept() # blocking call
.... # do something with the connection
For more information, visit the docs.
Additionally, you'd want to pass the details of the client socket to the thread. The server socket isn't required. In effect, something like this:
def handle_client(client_socket, client_address):
.... # do something with client socket
client_socket.close()
...
while True:
client_socket, client_address = mySocket.accept()
T = threading.Thread(target=handle_client, args=(client_socket, client_address))
T.start()
You accept the connection in the main loop, then pass the client details to the thread for processing.

Related

i want that client can send private message also from a broadcast server socket python

i have made a broadcast server and client both and i have used a message as command like #private to work as a command and and that will list all users and then i want that it should select one of them and then it can only chat with those client only which he as selected and on the backend broadcast also work for others
server()
# import socket programming library
import socket
import time
# import thread module
from _thread import *
import threading
def chatwithtwo(c,username,numusr,data):
c.send("choose to which one you wanna chat".encode())
for i in range(len(username)):
select=f"{i}. {username[i]}\n"
c.send(select.encode())
#here the thread gives problem
select_username=c.recv(1024)
print("select:",select_username.decode())
try:
if username[int(select_username)] in username:
chat_two_display(numusr,c,clients[int(select_username)])
else:
c.send("wrong selection".encode())
except:
c.send("wrong input".encode())
lock.release()
def chat_two_display(numusr,c,recver):
sendcheck={}
while True:
data = c.recv(1024)
sendcheck[numusr]=c
for i in range(len(clients)):
if clients[i]==recver:
send_to=usernames[i]
print(f"[+] {numusr} --> {send_to}:- {data.decode()}")
chat_two_send(numusr,data.decode(),recver)
def chat_two_send(numusr,data,recver):
sendingtoall=f"[+] {numusr} (private):- {data}"
recver.send(sendingtoall.encode())
def send_data(numusr,senddata,clients,sendcheck):
lock.release()
for i in range(len(clients)):
if not clients[i]==sendcheck[numusr]:
sendingtoall=f"[+] {numusr}:- {senddata}"
clients[i].sendall(sendingtoall.encode())
def display_data(c,numusr):
global lock
lock=threading.Lock()
sendcheck={}
while True:
time.sleep(0.5)
data = c.recv(1024)
sendcheck[numusr]=c
print(f"[+] {numusr}:- {data.decode()}")
lock.acquire()
if data.decode()=="#private":
#thread.acquire()
chatwithtwo(c,usernames,numusr,data)
else:
send_data(numusr,data.decode(),clients,sendcheck)
# thread function
def threaded(clients,username):
for i in range(len(clients)):
threading.Thread(target=display_data,args=(clients[i],username[i])).start()
def username_check(c):
while True:
uname=c.recv(1024)
if uname.decode() not in usernames:
datatosend=f"your username is {uname.decode()}"
usernames.append(uname.decode())
clients.append(c)
c.sendall(datatosend.encode())
break
else:
c.send("[-] This username is alredy in use!!!".encode())
def Main():
host = "127.0.0.1"
# reserve a port on your computer
# in our case it is 12345 but it
# can be anything
port = 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
print("socket binded to port", port)
# put the socket into listening mode
s.listen(5)
print("socket is listening")
global clients
global usernames
global threads
clients=[]
usernames=[]
threads=[]
connectio(s)
def connectio(s):
while True:
# establish connection with client
c, addr = s.accept()
# lock acquired by client
print('Connected to :', addr[0], ':', addr[1])
username_check(c)
# Start a new thread and return its identifier
threaded(clients,usernames)
if __name__ == '__main__':
Main()
client()
import socket
import threading
import time
def send_data(s):
while True:
message=input("")
s.send(message.encode('ascii'))
time.sleep(0.5)
if message=="close":
s.close()
def display_data(s):
while True:
data = s.recv(1024)
print(str(data.decode('ascii')))
time.sleep(0.5)
def Main():
# local host IP '127.0.0.1'
host = '127.0.0.1'
# Define the port on which you want to connect
port = 8000
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# connect to server on local computer
s.connect((host,port))
while True:
username=input("enter your username which should be unique:-")
s.send(username.encode())
username_check=s.recv(1024)
print(username_check.decode())
if username_check:
if username_check.decode()!="Try again":
break
# message you send to server
threading.Thread(target=send_data,args=(s,)).start()
threading.Thread(target=display_data,args=(s,)).start()
# close the connection
if __name__ == '__main__':
Main()
i have called a function for it that is chatwithtwo() but the problem is when select_username variable is receiving the value other threads also work at the same time all that get messed up please help me out in that
Just remove your for i in range(len(clients)): this from threaded function and all done
it will run your thread every time a client will connect to the server like if one client is connected then it will run for 1 time threads=1 running then the second time will run then its value will be 2 and the loop will run twice and the thread value fill get added to the last one like now running thread is 1 and after loop 2 more will be added and now threads are 3 and so on.

Persistent socket connection in Lua/Python

I'm trying to create a persistent socket connection between a Lua client and Python server. Effectively a script that'll constantly ping the server with keepalive messages
My current issue is that the socket closes after each connection without a means to reopen it for transmission.
Lua Client:
local HOST, PORT = "localhost", 9999
local socket = require('socket')
-- Create the client and initial connection
client, err = socket.connect(HOST, PORT)
client:setoption('keepalive', true)
-- Attempt to ping the server once a second
start = os.time()
while true do
now = os.time()
if os.difftime(now, start) >= 1 then
data = client:send("Hello World")
-- Receive data from the server and print out everything
s, status, partial = client:receive()
print(data, s, status, partial)
start = now
end
end
Python Server:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print("{} wrote".format(self.client_address[0]))
print(self.data)
print(self.client_address)
# Send back some arbitrary data
self.request.sendall(b'1')
if __name__ == '__main__':
HOST, PORT = "localhost", 9999
# Create a socketserver and serve is forever
with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
server.serve_forever()
The expected result is a keepalive ping every second to ensure the client is still connected to the server.
I ended up finding a solution.
The problem seems to have been with the socketserver library in Python. I switched it to raw sockets and things began working how I wanted them to. From there I created threads to handle the back and forth in the background
Python Server:
import socket, threading
HOST, PORT = "localhost", 9999
# Ensures the connection is still active
def keepalive(conn, addr):
print("Client connected")
with conn:
conn.settimeout(3)
while True:
try:
data = conn.recv(1024)
if not data: break
message = data.split(b',')
if message[0] == b'ping':
conn.sendall(b'pong' + b'\n')
except Exception as e:
break
print("Client disconnected")
# Listens for connections to the server and starts a new keepalive thread
def listenForConnections():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind((HOST, PORT))
while True:
sock.listen()
conn, addr = sock.accept()
t = threading.Thread(target=keepalive, args=(conn, addr))
t.start()
if __name__ == '__main__':
# Starts up the socket server
SERVER = threading.Thread(target=listenForConnections)
SERVER.start()
# Run whatever code after this
The Lua client didn't change in this scenario

How to send and receive from the same socket in Python?

I'm am trying to write a client program in Python that can send and receive from the same socket, but it is always giving me the same error which address is already in use. Here is the function I'm trying to write.
def Login():
username=raw_input()
password=raw_input()
message=raw_input()
array=[username,password,message]
TCP_IP = '127.0.0.1'
TCP_PORT = 5563
BUFFER_SIZE = 1024 # Normally 1024, but we want fast response
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((TCP_IP, TCP_PORT))
array_string=pickle.dumps(array)
sock.send(array_string)
sock.close()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((TCP_IP, TCP_PORT))
sock.listen(1)
conn, info = sock.accept()
while 1:
data = serverSocket.recv(1024)
if not data:break
conn.send(data)
conn.close()
There is a bunch of truly newbie errors here.
You can't ever connect a TCP socket to itself. There must be two different sockets.
If you really want to get the data you sent earlier at a listening socket, this listening socket must be created, bound and configured to listen before the client side connects (or, at least, in parallel to this connect attempt, in a few seconds, so the connect attempt will try - but this very likely won't work on localhost).
You can't wait on connect and on accept in the same thread if both are blocking. The simplest approach is to separate the client side and the server side to 2 different programs and run them manually in parallel. Then, after successful debugging, you will be able to do this in different threads of the same process, or using an event-driven engine.
While you may not be able to connect a socket to itself to send and receive data, you might be able to learn from the following example inspired by your code that attempts to do something similar.
import _thread
import pickle
import socket
import time
def main():
"""Run a server in a thread and start a client to talk to it."""
_thread.start_new_thread(run_server, ('', 5563))
run_client('localhost', 5563)
def run_server(host, port):
"""Handle all incoming connections by spawning worker threads."""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(5)
while True:
_thread.start_new_thread(handle_connection, server.accept())
def handle_connection(client, address):
"""Answer an incoming question from the connected client."""
print('Incoming connection from', address)
client.settimeout(0.1)
data = recvall(client)
client.shutdown(socket.SHUT_RD)
question = pickle.loads(data)
answer = '''len(username) = {}
len(password) = {}
len(message) = {}'''.format(*map(len, question))
client.sendall(answer.encode())
client.shutdown(socket.SHUT_WR)
client.close()
print('Finished with', address)
def recvall(connection):
"""Receive all data from a socket and return as a bytes object."""
buffer = bytearray()
while True:
try:
data = connection.recv(1 << 12)
except socket.timeout:
pass
else:
if data:
buffer.extend(data)
else:
return bytes(buffer)
def run_client(host, port):
"""Collect information from question and display returned answer."""
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
time.sleep(0.1) # wait for server to start listening for clients
client.connect((host, port))
time.sleep(0.1) # wait for handler thread to display connection
username = input('Username: ')
password = input('Password: ')
message = input('Message: ')
question = pickle.dumps((username, password, message))
client.sendall(question)
client.shutdown(socket.SHUT_WR)
answer = recvall(client)
client.shutdown(socket.SHUT_RD)
client.close()
print(answer.decode())
time.sleep(0.1) # wait for handler to cleanly terminate execution
if __name__ == '__main__':
main()

Python socket allow only one connection, but disconnect on new, not refuse

In python, you can define maximum number of socket connections by parameter of listen() function... for example:
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((socket.gethostname(), 80))
serversocket.listen(1) // allow only 1 connection
But the problem is that when second client wants to connect, connection is being refused. And I would like to disconnect the old user and connect the new one. Could anybody help me with that?
Probably an answer:
I am posting it in question as it is probable answer (I didn't have time to check it)
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((socket.gethostname(), 80))
serversocket.listen(10) // allow 10 connections, but disconnect previous later
someone_connected = 0
while 1:
(clientsocket, address) = serversocket.accept()
if(someone_connected) someone_connected.close()
someone_connected = clientsocket
I am not sure that I fully understand you question, but I think the following example can meet your requirement. the server can disconnect the old user and serve the new one.
the sever side:
#!/usr/bin/env python
import socket
import multiprocessing
HOST = '127.0.0.1'
PORT = 50007
# you can do your real staff in handler
def handler(conn, addr):
try:
print 'processing...'
while 1:
data = conn.recv(1024)
if not data:
break
print data
conn.sendall(data)
conn.close()
print 'processing done'
except:
pass
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(5)
processes = []
while True:
conn, addr = s.accept()
print conn, addr
[p.terminate() for p in processes] # to disconnect the old connection
# start process newer connection and save it for next kill
p = multiprocessing.Process(target=handler, args=(conn, addr))
processes = [p]
p.start()
newest_conn = conn # this is the newest connection object, if you need it
For test, the client side:
#!/usr/bin/env python
import socket
import time
import multiprocessing
HOST = '127.0.0.1'
PORT = 50007
def client():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
time.sleep(0.1)
try:
for n in range(20):
s.send(str(n))
data = s.recv(1024)
print data
time.sleep(0.5)
s.send('')
s.close()
except:
pass
if __name__ == "__main__":
for i in range(5):
print 'user %i connect' %i
p = multiprocessing.Process(target=client)
p.start() # simulate a new user start connect
time.sleep(3)
Try it :-)
You have a wrong assumption built into your question - the single argument to socket listen() is not the "number of connections", but a backlog - number of pending, but not yet accepted client connections the kernel holds for you for a while.
Your problem then seems to be that you have accepted one connection, and reading/writing to it in a loop, and not calling accept() again. The kernel holds the request for any new client connection for some timeout, then notifies the client that the server is not accepting it.
You want to look into select() functionality, as suggested in the comments.

Python 3: Socket server send to multiple clients with sendto() function

I have a server set up with sockets and threading, and when I connect multiple clients to it, if a client sends a message, the server repeats that same message back to it, instead of to all other connected clients. For example:
#server terminal
Server is connected on 8000
('127.0.0.1', 50328) is Connected
('127.0.0.1', 50329) is Connected
Received Message b'hi\n'
#Client 1 terminal
#input
[user1]hi
#returns:
[user1] b'hi\nhi\n'[user1]
#Client 2 terminal
#doesn't return anything, just sits at the prompt
[user2]
The relevant code for the server is:
def clientHandler():
c, addr = s.accept()
print(addr, "is Connected")
if addr not in clients:
clients.append(addr)
try:
while True:
data = c.recv(1024)
if not data:
break
print("Received Message ", repr(data))
for client in clients:
c.sendto(data, client)
except:
print("Error. Data not sent.")
I have read the following sources, but to no avail:
python tcp server sending data to multiple clients
https://docs.python.org/3/library/socket.html
What must I do to make it send user1's message to all other users through the server?
Edit 1:
All server.py code:
from socket import *
from threading import Thread
clients = []
def clientHandler():
c, addr = s.accept()
print(addr, "is Connected")
if addr not in clients:
clients.append(addr)
try:
while True:
data = c.recv(1024)
if not data:
break
for client in clients:
c.sendto(data, client)
except:
print("Error. Data not sent to all clients.")
HOST = '' #localhost
PORT = 8000
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
print("Server is running on "+ str(PORT))
#Thread(target=clientHandler).start()
#Thread(target=clientHandler).start()
#Thread(target=clientHandler).start()
for i in range(5):
Thread(target=clientHandler).start()
s.close()
I see a few issues in your code -
You are starting clientHandler threads, but then you are not making the main thread join any , this may cause main thread to die before the child threads finish processing, I think you would want to save the Thread objects you create to a variable and then make them join the main thread.
Instead of making the clientHandlers directly, you should first wait for accepting a connection from client (outside the handler function) and once you get the connection, add it to list of clients and send it over to the clientHandler.
In your code - for client in clients: c.sendto(data, client) m this sends data to all clients ,instead you should check if client is not the client that this thread is servicing, by checking against the addr that this thread is servicing.
Example changes -
from socket import *
from threading import Thread
clients = []
def clientHandler(c, addr):
global clients
print(addr, "is Connected")
try:
while True:
data = c.recv(1024)
if not data:
break
for client in clients:
if addr != client:
c.sendto(data, client)
except:
print("Error. Data not sent to all clients.")
HOST = '' #localhost
PORT = 8000
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
print("Server is running on "+ str(PORT))
#Thread(target=clientHandler).start()
#Thread(target=clientHandler).start()
#Thread(target=clientHandler).start()
trds = []
for i in range(5):
c, addr = s.accept()
clients.append(addr)
t = Thread(target=clientHandler, args = (c, addr))
trds.append(t)
t.start()
for t in trds:
t.join()
s.close()

Categories

Resources