Python : Creating a socket in a thread - python

I am trying to create a socket IN A THREAD, but i am unable to do so.
My code is
#!/usr/bin/env python
import threading
import socket
class test1():
def serve(self):
host = ''
port = 9999
th_obj = threading.Thread(target = self.thread_method, args = (host,port))
th_obj.daemon = True
th_obj.start()
def thread_method(self,host,port):
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
sock.bind(('',9999))
sock.listen(5)
while True:
connection, addr = sock.accept()
connection.settimeout(60)
while True:
data = connection.recv(2048)
t = open('file.txt', 'a')
t.write(data)
test1().serve()
The problem is the script won't when I set daemon = True while it is working perfectly without it.
How can i solve this problem. It is essential to me to demonize it.

Related

How to send a chatlog of all written chats to a newly joined client using socket programming in Python?

I have written a simple server and client py using UDP. The base is working, however I want that every time a user (client) joins, he would receive a chatlog of everything that has been said.
This is my code until now:
Server:
import socket
import threading
import queue
import pickle
messages = queue.Queue()
clients = []
# AF_INET used for IPv4
# SOCK_DGRAM used for UDP protocol
ip = "localhost"
port = 5555
chatlog=[]
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# binding IP and port
UDPServerSocket.bind((ip, port))
def receive():
while True:
try:
message, addr = UDPServerSocket.recvfrom(1024)
messages.put((message, addr))
chatlog.append((message,addr))
except:
pass
def broadcast():
while True:
while not messages.empty():
message, addr = messages.get()
print(message.decode())
if addr not in clients:
clients.append(addr)
for client in clients:
try:
if message.decode().startswith("SIGNUP_TAG:"):
name = message.decode()[message.decode().index(":") + 1:]
UDPServerSocket.sendto(f"{name} joined!".encode(), client)
if len(chatlog)>0:
sending= pickle.dumps(chatlog)
UDPServerSocket.sendto(sending, client)
else:
pass
else:
UDPServerSocket.sendto(message, client)
except:
clients.remove(client)
t1 = threading.Thread(target=receive)
t2 = threading.Thread(target=broadcast)
t1.start()
t2.start()
And the client
import socket
import threading
import random
client= socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.bind(("localhost", random.randint(7000, 8000))) # random port for every client
name = "Henk" #test name
def receive():
while True:
try:
message, _ = client.recvfrom(1024)
print(message.decode())
except:
pass
t= threading.Thread(target= receive)
t.start()
#this gives the server the name of the people who have entered the server
client.sendto(f"SIGNUP_TAG: {name}".encode(), ("localhost", 5555))
while True:
message= input("")
if message=="!q":
exit()
else:
client.sendto(f'[{name}]: {message}'.encode(), ("localhost",5555))
So I am actually a bit stuck on how I will approach this. Shall create a text file where every time that a message is written it gets written on the file as well? Or shall I create some kind of string list/database where every message is stored :/

Python socket connection error: OSError: [Errno 9] Bad file descriptor

I am trying to write a client/server program in python that will accept multiple connections and manage them using threading. The server and client both run, and the client will receive the "welcome" message from the servers "processClient" function, which means the connection is being made and the thread is being started. However, any subsequent receive or send on the connection object after the welcome message fails with an "OSError: [Errno 9] Bad file descriptor" error. I've done some searching on the error, and most problems seem to result from someone trying to use a socket or connection that's been previously closed-which should not be the case here. Does anyone know what could be causing the error? Running python version 3.5.2
Server code:
#!/usr/bin/env python3
import socket
import sys
import os
import datetime
import threading
import random
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
def processClient(conn, id):
welcome = "Hello, you are client number " + str(id)
welcome = bytes(welcome, 'utf-8')
conn.sendall(welcome)
while True:
data = conn.recv(1024)
print(rpr(data))
time = str(datetime.datetime.now())
arr = bytes(time, 'utf-8')
if data == b'time':
conn.sendall(arr)
elif data == b'':
conn.close()
return
else:
temp = data.decode("utf-8")
temp = temp.upper()
temp = bytes(temp, 'utf-8')
conn.sendall(temp)
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("unable to create socket connection, shutting down.")
quit()
s.bind(('0.0.0.0', PORT))
s.listen()
sys.stdout.write("Server is running \n")
runningThreads = []
threadID = 0
while True:
conn, addr = s.accept()
with conn:
#conn.setblocking(False)
print('Connected by', addr)
threadID += 1
threadTemp = threading.Thread(target = processClient, args=(conn, threadID))
threadTemp.start()
runningThreads.append(threadTemp)
for t in runningThreads:
if not t.isAlive():
# get results from thtead
t.handled = True
threadID -= 1
else:
t.handled = False
runningThreads = [t for t in runningThreads if not t.handled]
Client code:
#!/usr/bin/env python3
import socket
import sys
import os
import datetime
HOST = 0
while HOST == 0 or HOST == "":
HOST = input("Please enter host IP: ")
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
data = s.recv(1024)
print(repr(data))
while True:
inputString = input("Please input a string: ")
temp = bytes(inputString, 'utf-8')
s.sendall(temp)
if inputString == "":
quit()
data = s.recv(1024)
if data:
print(rpr(data))
for anyone else who stumbles across this: I did finally work out the problem. The server was not waiting on input from the client before it attempts to read data from the connection, which was triggering the error (the error message was particularly unhelpful in diagnosing this issue). I rewrote this to use python selectors rather than threads-selectors includes very handy polling functionality that can be used to "pause" until there is data to be read. I could have built this into the program myself, but why do so when there's already a language feature that does it for you?

Cant run Python UDP server with OOP

i Try to create udp port listener using OOP but i try to start server it not start. In python console it only show
=============RESTART: D:\server.py==================
>>>
this is my code
import threading
import time
import socket
class udpreceive:
def __init__(self,port,ip):
self.port = port
self.ip = ip
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((self.ip, self.port))
def startserver(self):
while True:
time.sleep(1)
data, addr = self.sock.recvfrom(1024)
print (data)
server1 = udpreceive(514,"192.168.1.5")
t1 = threading.Thread(target=server1.startserver)
what is the error? I'm new to OOP and socket programming Thanks

Python: Accept connections into a list, and have the user select a specific socket to write to?

Python: Accept connections into a list, and have the user select a specific socket to write to?
I want to program a simple Python server that accepts incoming connections, stores them into a list, and has a user-interface that lets the user select which socket to write to.
So, while the server accepts new connections and prints received data to screen, the user should have a UI like:
> select 2 # select connection 2
> helloworld # writes 'helloworld' to the socket
How can I do this using threads or subprocesses? (what is the best approach?)
Bonus: How can I do so, that received data don't mess with the UI prompt?
This is my code using select.select():
#!/usr/bin/env python3
import os
import sys
import select
import socket
TCP_IP = '0.0.0.0'
TCP_PORT = 80
BUF_SZ = 1024
sock_list = []
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((TCP_IP,TCP_PORT))
server.listen(10)
inputs = [server]
outputs = []
while True:
read_socks, write_socks, error_socks = select.select(inputs, outputs, inputs)
for sock in read_socks:
if sock is server:
conn,addr = server.accept()
inputs.append(conn)
print('Connection %s' % conn)
else:
data = sock.recv(BUF_SZ)
print(data)
for sock in write_socks:
None
To use threading you can simply wait on socket.accept() and when you receive a new connection handle it using a new thread. A sample code can be like this:
import socket
import sys
import threading
def worker(conn, ip, port, max_buffer_size=4096):
print('accepting connection from ip={} and port={}'.
format(ip, port, conn))
data = conn.recv(max_buffer_size)
# Do something
conn.close()
def init_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(PARALLEL_CONNECTIONS)
return server_socket
def run():
try:
s = init_server()
print('successfully created server socket.')
except Exception as e:
print('failed to create socket because {}'.format(e))
sys.exit()
while True:
clientsocket, addr = s.accept()
ip, port = str(addr[0]), str(addr[1])
t = threading.Thread(target=worker, args=(clientsocket, ip, port,))
t.start()

Server process started by multiprocessing.Manager() makes piped socket not closed immediately

I have following code, server accept net connection, pass it to child to process with Manager().Queue():
q = Manager().Queue()
class Server:
def run(self, host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
print('parent', os.getpid())
while True:
c, _ = s.accept()
q.put(c)
c.close()
def handle_request():
print('child', os.getpid())
while True:
c = q.get()
time.sleep(1)
print(c.recv(4))
c.close()
Process(target=handle_request, args=()).start()
Server().run('127.0.0.1', 10000)
close doesn't work as expected, I think it is because Manager's server process sill have a reference on that socket, lsof -i confirmed. How to deal with this? I found there is not a way to close the socket in Manager process, shutdown could do the trick but not what I want.
Interesting problem.
I am not sure if this is of any help, but I found your code somewhat odd in the beginning, as sending socket objects using Manager().Queue() to another process does not sound like it is supported. It may be, but sending a file descriptor to another process needs a couple of hoops. I changed your code a bit to do it as I would do it - basically reducing and reconstructing handles.
from multiprocessing import Manager, Process
from multiprocessing.reduction import reduce_handle, rebuild_handle
import socket
import os
from time import sleep
q = Manager().Queue()
class Server:
def run(self, host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)
print('parent', os.getpid())
while True:
c, _ = s.accept()
foo = reduce_handle(c.fileno())
q.put(foo)
c.close()
def handle_request():
print('child', os.getpid())
while True:
bar = q.get()
sleep(1)
barbar = rebuild_handle(bar)
c = socket.fromfd(barbar, socket.AF_INET, socket.SOCK_STREAM)
print(c.recv(4))
c.shutdown(socket.SHUT_RDWR)
Process(target=handle_request, args=()).start()
Server().run('127.0.0.1', 10000)
This does not leave any sockets behind in CLOSE_WAIT at least when I ran it, and it works as I would expect it to work.

Categories

Resources