Chat with python thread. Program do not exit - python

I'm studying python building a chat with socket and thread. The problem is that my client does not properly exist when I execute or or type "/quit". The program ends, but the prompt does not back. I think my thread is running yet.
What I'm doing wrong?
# -*- coding: UTF-8 -*-
import socket
from threading import Thread
class Client(Thread):
def __init__(self, server_host, server_port):
Thread.__init__(self)
self.server_host = server_host
self.server_port = server_port
def run(self):
self.connect()
self.accepting = True
self.rec_message()
def connect(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.server_host, self.server_port))
print 'Conectado ao servidor %s:%s' % (self.server_host, self.server_port)
def close(self):
print 'Fechar'
self.sock.close()
self.accepting = False
def send_message(self, msg):
self.sock.sendall(msg)
def rec_message(self):
while self.accepting:
print self.sock.recv(1024)
# Criar objeto da classe cliente
HOST = '127.0.0.1'
PORT = 38267
client = Client(HOST, PORT)
client.start()
msg = raw_input()
while msg <> '/quit':
client.send_message(msg)
msg = raw_input()
client.close()

Related

ECONNABORTED when attempting to connect ESP32 and ESP8266

I'm attempting to connect an ESP32 and ESP8266 via sockets with micropython. I cannot get the ESP8266 client to connect to the ESP32 server without throwing an ECONNABORTED 103 error. Code is below, not sure what I'm doing wrong here. This seems to work when working off of my laptop and had no issues until trying to connect these two specific devies.
ESP32 Server Code:
import network
import socket
from time import sleep
SSID = 'esp'
KEY = 'meow'
ADDR = '192.168.4.1'
PORT = 2000
class socket_master:
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind(('',PORT))
self.attempt = 0
def accept_connection(self):
self.sock.listen(4)
self.conn, self.addr = self.sock.accept()
def test_speed(self):
data = 'attempt ' + str(self.attempt)
self.conn.sendall(data.encode())
self.attempt += 1
attempt = 0
try:
print('starting network')
ap = network.WLAN(network.AP_IF)
print('network started')
if ap.active() == False:
ap.active(True)
sleep(1)
ap.config(essid='esp')
print(ap.config('essid'))
print('set ssid')
print(ap.ifconfig())
except:
print('failed')
sm = socket_master()
sm.accept_connection()
print('waiting for client')
while True:
sm.test_speed()
ESP8266 Client Code:
# main.py -- put your code here!
import network
import socket
SSID = 'esp'
KEY = 'meow'
ADDR = '192.168.4.1'
PORT = 2000
def do_connect():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.connect('esp')
while not wlan.isconnected():
pass
print('network config:', wlan.ifconfig())
class socket_master_2:
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((ADDR,PORT))
def receive_print(self):
data = self.sock.recv(1024)
print(data)
print(data.decode())
do_connect()
client = socket_master_2()
while True:
client.receive_print()

Python : threads can only be started once

I'm writing a simple chat, for the moment it just connect an user.
bootchat/
--server.py
--client.py
--libbootchat/
--bootchat_connection.py
--bootchat_server.py
--bootchat_user.py
Code:
client.py
# imports
import libbootchat.bootchat_user as user
import socket
print("Welcome on BootChat")
nickname = input("nickname : ")
bootchat_user = user.BootchatUser(nickname)
server.py
# imports
import socket
import signal
import libbootchat.bootchat_server as server
import libbootchat.bootchat_connection as connection
print("Starting server...")
bootchat_server = server.BootchatServer()
while True:
bootchat_server.accept_connection()
bootchat_server.start()
bootchat_connection.py
class BootchatConnection():
def __init__(self, socket, informations=None):
self.socket = socket
if informations:
self.ip = informations[0]
self.port = informations[1]
def connect_to_server(self, ip, port):
self.socket.connect((ip, port))
def send_to_server(self, msg):
self.socket.send(msg.encode())
def recv_from_client(self):
return self.socket.recv(1024).decode()
bootchat_user.py
from libbootchat.bootchat_connection import BootchatConnection
import socket
class BootchatUser:
nb_users = 0
def __init__(self, nickname):
self.nickname = nickname
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.bootchat_connection = BootchatConnection(connection)
self.bootchat_connection.connect_to_server("localhost", 15297)
self.send_message(nickname)
def send_message(self, msg):
self.bootchat_connection.send_to_server(msg)
bootchat_server.py
import socket
from threading import Thread
from libbootchat.bootchat_connection import BootchatConnection
class BootchatServer(Thread):
def __init__(self):
Thread.__init__(self)
self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.listener.bind(('', 15297))
self.listener.listen(5)
def accept_connection(self):
socket, infos = self.listener.accept()
self.bootchat_connection = BootchatConnection(socket, infos)
def run(self):
print("[INFO] New user connected from {}".format(self.bootchat_connection.ip))
nickname = self.bootchat_connection.recv_from_client()
print("[INFO] User from {} now logged at {}".format(self.bootchat_connection.ip, nickname))
Problem:
I start server and i start a first client, and I send a nickname and I have no problems, my server print correctly "New user connected...", but after, I start a second client, and I have an error. This is the output of my server.py :
Starting server...
[INFO] New user connected from 127.0.0.1
[INFO] User from 127.0.0.1 now logged at Alex
Traceback (most recent call last):
File "server.py", line 14, in <module>
bootchat_server.start()
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/threading.py", line 840, in start
raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once
Any ideas ? Thank you
Generate a new thread for each connection:
class BootchatServer(object):
def __init__(self):
self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.listener.bind(('', 15297))
self.listener.listen(5)
def accept_connection(self):
socket, infos = self.listener.accept()
connection = BootchatConnection(socket, infos)
thread = Thread(target=self.process_connection, args=(connection,))
thread.start()
def process_connection(self, connection):
print("[INFO] New user connected from {}".format(connection.ip))
nickname = connection.recv_from_client()
print("[INFO] User from {} now logged at {}".format(connection.ip, nickname))
print("Starting server...")
bootchat_server = server.BootchatServer()
while True:
bootchat_server.accept_connection()

Manipulating socketstream in Python

I'm trying to create a small, multithreaded proxyscript that allows me to proxy LDAP requests and manipulate the results (like adding extra fields, renaming them etc).
In the example below, I try to replace the field 'TEST' by 'DONE'. Is there any solution to allow this socketstream to be manipulated? Should I decode it somewhat first?
import select
import socket
import sys
import threading
import signal
import re
import random
import time
import binascii
from ldaptor.protocols import pureldap, pureber
from time import gmtime, strftime
ASTLDAP_PROXY_PORT = 1389
ASTLDAP_HOST = 'localhost'
ASTLDAP_PORT = 389
BUFFERSIZE = 1024
DELAY = 0.0001
class Forward:
def __init__(self):
self.forward = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def start(self, host, port):
try:
self.forward.connect((host, port))
return self.forward
except Exception, e:
print e
return False
class AstLdapProxyServer(threading.Thread):
input_list = []
channel = {}
def __init__(self, host, port, socket):
threading.Thread.__init__(self)
self.host = host
self.port = port
# Socket ontvangen die we meekregen bij nieuwe thread.
self.socket = socket
print "[+] New thread started for "+host+":"+str(port)
self.socket.bind((host, port))
self.socket.listen(200)
def register_signals(self):
signal.signal(signal.SIGHUP, self.signal_handler)
signal.signal(signal.SIGINT, self.signal_handler)
signal.signal(signal.SIGQUIT, self.signal_handler)
def main_loop(self):
self.input_list.append(self.socket)
while 1:
#time.sleep(DELAY)
ss = select.select
inputready, outputready, exceptready = ss(self.input_list, [], [])
for self.s in inputready:
if self.s == self.socket:
self.on_accept()
break
self.data = self.s.recv(BUFFERSIZE)
if len(self.data) == 0:
self.on_close()
else:
self.on_recv()
def on_accept(self):
forward = Forward().start(ASTLDAP_HOST, ASTLDAP_PORT)
clientsock, clientaddr = self.socket.accept()
if forward:
print clientaddr, "has connected"
self.input_list.append(clientsock)
self.input_list.append(forward)
self.channel[clientsock] = forward
self.channel[forward] = clientsock
else:
print "Can't establish connection with remote server.",
print "Closing connection with client side", clientaddr
clientsock.close()
def on_close(self):
print self.s.getpeername(), "has disconnected"
#remove objects from input_list
self.input_list.remove(self.s)
self.input_list.remove(self.channel[self.s])
out = self.channel[self.s]
# close the connection with client
self.channel[out].close() # equivalent to do self.s.close()
# close the connection with remote server
self.channel[self.s].close()
# delete both objects from channel dict
del self.channel[out]
del self.channel[self.s]
def on_recv(self):
data = self.data
# Manipulate result
output = re.sub(r'uzgEmail1', r'TEST', data)
# Send result to client (DOESN'T WORK)
self.channel[self.s].send(output)
# Send result to client (WORKS when I disable send above)
self.channel[self.s].send(data)
if __name__ == '__main__':
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
server = AstLdapProxyServer(ASTLDAP_HOST, ASTLDAP_PROXY_PORT, tcpsock)
server.start()
try:
server.main_loop()
except KeyboardInterrupt:
sys.exit(1)

Multithreaded socket programming in python

I am working on client/server socket programming using python. I could set it up without any issue, but with threads, I am lost. I don't have a clue how to get that part done. I looked at the python documentation as well, but I could not find what I was expecting.
What I am trying to achieve is - Server is accepting the connection from the client as well as monitoring a directory for any file creation. I am trying to run both of them in parallel, but it didn't work.
#!/usr/bin/python # This is server.py file
import socket # Import socket module
import sys,os
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.challenger", "*.challenger"]
def process(self, event):
"""
event.event_type
'modified' | 'created' | 'moved' | 'deleted'
event.is_directory
True
event.src_path
/home/abcd/Maildir/new/
"""
# the file will be processed there
print event.src_path, event.event_type # print now only for degug
def on_modified(self, event):
self.process(event)
flag = '1'
print flag
def on_created(self, event):
self.process(event)
def on_any_event(self,event):
if event.event_type == 'created':
send()
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12346 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
flag = '0'
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
# c.send('Thank you for connecting')
# c.send(flag)
if __name__ == '__main__':
args = sys.argv[1:]
observer = Observer()
observer.schedule(MyHandler(), path='/home/abcd/Maildir/new')
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
c.send(flag)
c.close() # Close the connection
The code I posted is without threads because with thread it didn't work at all.
I am using watchdog to monitor /home/abcd/Maildir/new to monitor any new e-mail file created, and if it is created I want to send acknowledgement (flag, in this case) to the client that the e-mail has been received. Socket connection and Watchdog worked well individually, but I don't know why they wouldn't work together? :(
How can I put these methods in different threads so that they run parallelly? Thanks for your help.
EDIT: code after Craig's input:
import threading
import socket # Import socket module
import sys,os
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
def send_message(conn, flag):
conn.send(flag)
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.challenger", "*.challenger"]
def __init__(self, conn, *args, **kwargs):
super(MyHandler, self).__init__(*args, **kwargs)
self.conn_list = conn
def process(self, event):
"""
event.event_type
'modified' | 'created' | 'moved' | 'deleted'
event.is_directory
True
event.src_path
/home/abcd/Maildir/new/
"""
print "I reached here too"
time.sleep(5)
print event.src_path, event.event_type # print now only for degug
def on_created(self, event):
flag = '1'
threads = [threading.Thread(target=send_message, args=(conn, flag)) for conn in self.conn_list]
for t in threads:
t.start()
print "on_created"
self.process(event)
for t in threads:
t.join()
from collections import deque
conn_list = deque()
if __name__ == '__main__':
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12346 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
flag = '0'
s.listen(5) # Now wait for client connection.
observer = Observer()
observer.schedule(MyHandler(conn_list), path='/home/abcd/Maildir/new/')
observer.start()
print "Before True"
while True:
try:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
conn_list.append(c)
time.sleep(1)
print "I started Observer"
except KeyboardInterrupt:
observer.stop()
while conn_list:
conn_list.pop().close()
print "Connections closed"
break
observer.join()
EDIT 2 :
When I send e-mail from client to server, I get the correct result first time but when I connect one more time, the output is weird ("In message" prints twice, flag value also prints twice and I get broken pipe error)
Modified Server.py after Craig's input:
import threading
import socket # Import socket module
import sys,os
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
def send_message(conn, flag):
print "In message"
conn.send(flag)
print "flag"+flag
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.challenger", "*.challenger"]
def __init__(self, conn, *args, **kwargs):
super(MyHandler, self).__init__(*args, **kwargs)
self.conn_list = conn
def process(self, event):
time.sleep(5)
print "In process"
print event.src_path, event.event_type # print now only for degug
def on_created(self, event):
flag = '1'
print "before process event"
self.process(event)
print "after process, before thread target"
threads = [threading.Thread(target=send_message, args=(conn, flag)) for$
flag = '0'
for t in threads:
t.start()
# print "Before process(Event)"
# self.process(event)
print "after process event"
for t in threads:
t.join()
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
flag = '0'
s.listen(5) # Now wait for client connection.
print "flag before: "+flag
from collections import deque
conn_list = deque()
if __name__ == '__main__':
observer = Observer()
observer.start()
args = sys.argv[1:]
observer.schedule(MyHandler(conn_list), path='/home/abcd/Maildir/new')
while True:
try:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
flag = '0'
print flag
conn_list.append(c)
except KeyboardInterrupt:
observer.stop()
while conn_list:
conn_list.pop().close()
print "Connections closed"
break
observer.join()
Here's the output:
Got connection from ('72.123.27.223', 39844)
0
before process event
In process
/home/abcd/Maildir/new/1425403821.V801I2ac232cM275759.challenger created
after process, before thread target
In message
In message
flag1In message
after process event
flag1
Exception in thread Thread-7:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/paras/server42.py", line 11, in send_message
conn.send(flag)
error: [Errno 32] Broken pipe
Here's my client.py - All I am trying to do is check e-mail latency from client to server and getting response back from the server.
#!/usr/bin/python # This is client.py file
import sys,smtplib
import socket # Import socket module
import threading,time
import urllib
import random
import datetime
#class myThread(threading.Thread):
# def __init__ (self,name):
# threading.Thread.__init__(self)
# self.name=name
# def run(self):
# connection()
# print "Starting"+self.name
def connection():
s = socket.socket() # Create a socket object
host = socket.gethostbyname('server.edu') # Get local machine name
port = 12345 # Reserve a port for your service.
try:
s.connect((host, port))
# print s.recv(1024)
t1 = datetime.datetime.now()
sendmail()
t2 = datetime.datetime.now()
print str(t1),str(t2)
print "Time taken to send e-mail from client to server: "+str(t2-t1)
print "came back"
flag = s.recv(1024)
print flag
if (flag=='1'):
t3=datetime.datetime.now()
print "Time taken to receive response from server: "+str(t3-t2)
s.close # Close the socket when done
except KeyboardInterrupt:
s.close
def sendmail():
fromaddr = 'xyz#gmail.com'
toaddrs = 'email#server.edu'
url = "http://www.google.com"
seq = str(random.randint(1,9))
msg = 'URL: '+ url + '\n'+'SEQ:'+seq+'\n'
print "In sendmail"
#print msg
# Credentials (if needed)
username = 'xyz#gmail.com'
password = 'somepassword'
#The actual mail send
server = smtplib.SMTP('smtp.gmail.com:587')
#server = smtplib.SMTP('localhost')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
print "email sent"
return
if __name__ == "__main__":
connection()
Please help me out. Thanks.
This doesn't exactly do what you asked since the server doesn't send the data but I think it achieves what you want to do. You could pass along connection object so that you can send the flag to it from MyHandler.
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.challenger", "*.challenger"]
def __init__(self, conn, *args, **kwargs):
super(MyHandler, self).__init__(*args, **kwargs)
self.conn_list = conn
def process(self, event):
time.sleep(5)
print event.src_path, event.event_type # print now only for degug
def on_created(self, event):
self.process(event)
c = self.conn_list.pop()
c.send('1')
c.close()
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12346 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
flag = '0'
s.listen(5) # Now wait for client connection.
from collections import deque
conn_list = deque()
if __name__ == '__main__':
observer = Observer()
observer.start()
args = sys.argv[1:]
observer.schedule(MyHandler(conn_list), path='/home/abcd/Maildir/new')
while True:
try:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
conn_list.append(c)
except KeyboardInterrupt:
observer.stop()
while conn_list:
conn_list.pop().close()
print "Connections closed"
break
observer.join()

Connecting to server over RCON

Why does this code return what I need:
test2.py
import socket
if __name__ == "__main__":
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect(("192.168.0.101", 28960))
sock.send(b"\xFF\xFF\xFF\xFFrcon xxxxxxxxx status")
print (sock.recv(65565))
sock.close()
Desired Output:
b'\xff\xff\xff\xffprint\nmap:mp_rust\nnum score ping guid name lastmsg address qport rate\n
--- ----- ---- -------------------------------- --------------- ------- --------------------- ----- -----\n\n\x00'
but this code always returns:
b'\xff\xff\xff\xffdisconnect\x00'
My Code
test.py
import socket
from models import RconConnection
if __name__ == "__main__":
connection = RconConnection("192.168.0.101", 28960)
connection.connect()
connection.auth("xxxxxxxx")
connection.send("status")
print(connection.response(128))
models.py
import socket
class RconConnection(object):
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def connect(self):
self.socket.connect(("%s" % (self.ip), self.port))
return 1
def auth(self, password):
string = "\xFF\xFF\xFF\xFFrcon_password %s" % (password)
self.socket.send(bytearray(string, "utf-8"))
return 1
def send(self, command):
string = "\xFF\xFF\xFF\xFFrcon %s" % (command)
self.socket.send(bytearray(string, "utf-8"))
return 1
def response(self, size):
string = self.socket.recv(size)
return string
Test2.py and (test.py + models.py) don't run at same time. Where the difference between test2.py and it OO-realization in test.py and models.py?
It seems both the sockets are trying to send data once the connection is established.
...
sock.connect(("192.168.0.101", 28960))
sock.send(b"\xFF\xFF\xFF\xFFrcon xxxxxxxxx status") # here
...
And
...
connection.connect()
connection.auth("xxxxxxxx") # here
connection.send("status") # and here!
...
Make one/both of the receive/send the data when the other is doing the opposite, like I have done for the client socket below (so that no changes have to be made to the Rcon calls)...
import socket
if __name__ == "__main__":
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect(("192.168.0.101", 28960))
auth = sock.recv() # recieve "xxxxxxxx" (auth)
status = sock.recv() # recieve "status"
sock.send(b"\xFF\xFF\xFF\xFFrcon xxxxxxxxx status")
sock.close()
print "Auth:", auth
print "Status:", status

Categories