I'm making a simple python chatroom type server, and I am trying to implement server commands. Sending and receiving messages work fine but for some reason when I send a server command It gets received weird. I assume it's how the message is being sent that's causing it to act weird because the server sends server commands separately from how it sends regular messages. Here are the snippets that I think are the problem:
SERVER SIDE:
userData = "server".encode("utf-8")
userHeader = f"{len(userData):<{HEADER_LENGTH}}".encode("utf-8")
print(userHeader)
command = str(command)
messageData = f"cmd${command}".encode("utf-8")
messageHeader = f"{len(command):< {HEADER_LENGTH}}".encode("utf-8")
for client_socket in self.clients:
client_socket.send(userHeader + userData + messageHeader + messageData)
window.logData(f"sent server command {command}")
window.logChat("SERVER",command)
This gets called when a button is pressed and then some input is passed in as the command
Here's how the client receives data:
while True:
try:
username_header = self.client_socket.recv(HEADER_LENGTH)
if(not len(username_header)):
print("connection closed by server")
sys.exit()
print(username_header.decode("utf-8").strip())
username_length = int(username_header.decode("utf-8").strip())
username = self.client_socket.recv(username_lenght).decode("utf-8")
message_header = self.client_socket.recv(HEADER_LENGTH)
message_length = int(message_header.decode("utf-8").strip())
messageRaw = self.client_socket.recv(message_length).decode("utf-8")
type_, message = messageRaw.split("$")
if(type_ == "message"):
GUI.outgoing.insert(END, "")
GUI.incoming.insert(END, f"{username} >> {message}")
elif(type_ == "cmd"):
if(username == "sever"):
print("recieved server command")
except IOError as e:
if(e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK):
print("READ ERR",str(e))
sys.exit()
continue
I'm not getting any errors on the server side but I am on the client side so here's the output:
6
TEST
Exception in thread Thread-1:
Traceback (most recent call last):
File "/home/kali/anaconda3/lib/python3.7/threading.py", line 926, in _bootstrap_inner
self.run()
File "/home/kali/anaconda3/lib/python3.7/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "client.py", line 119, in main
username_lenght = int(username_header.decode("utf-8").strip())
ValueError: invalid literal for int() with base 10: 'TEST'
I'm sending the text "TEST" to see if the server is receiving data, where it prints the length of the username header it prints 6 which is the length "SERVER" but it also prints "TEST" which is where everything goes wrong.
If you want to play around with the code the github page is https://github.com/snakebite-382/Chatty.py/tree/unstable make sure you download the scripts from the unstable branch. The stable branch has the first release which doesn't have a GUI or the ability to send server commands.
Related
So here is something wrong.
I try to implement a simple Web Server in Python using socket. The single-thread version runs well but, when I try to implement more threads with non-blocking mode, it comes with errors. I searched on Stack Overflow and Google, but no answers.
Here is my code:
# coding:utf-8
import errno
import socket
import threading
import time
EOL1 = b'\n\n'
EOL2 = b'\n\r\n'
body = '''<h1>Hello, world!</h1> - from {thread_name}'''
response_params = [
'HTTP/1.0 200 OK',
'Date: Mon, 01 jan 2022 01:01:01 GMT'
'Content-Type: text/plain; charset=utf-8',
'Content_Length: {length}\r\n',
body,
]
response = '\r\n'.join(response_params)
def handle_connection(conn, addr):
# print(conn, addr)
# time.sleep(60)
request = b""
while EOL1 and EOL2 not in request:
request += conn.recv(1024) # ERROR HERE!
print(request)
current_thread = threading.currentThread()
content_length = len(body.format(thread_name=current_thread.name).encode())
print(current_thread.name)
conn.send(response.format(thread_name=current_thread.name,
length = content_length).encode())
conn.close()
def main():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
serversocket.bind(('127.0.0.1', 8000))
serversocket.listen(10)
print('http://127.0.0.1:8000')
serversocket.setblocking(0)
try:
i = 0
while True:
try:
conn, address = serversocket.accept()
except socket.error as e:
if e.args[0] != errno.EAGAIN:
raise
continue
i += 1
print(i)
t = threading.Thread(target=handle_connection, args=(conn, address),
name = 'thread-%s' % i)
t.start()
finally:
serversocket.close()
if __name__ == '__main__':
main()
The Error message is here:
1
Exception in thread thread-1:
2
Traceback (most recent call last):
File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 973, in _bootstrap_inner
Exception in thread thread-2:
Traceback (most recent call last):
File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 973, in _bootstrap_inner
self.run()
self.run()
File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 910, in run
File "/Users/tdeveloper/opt/anaconda3/lib/python3.9/threading.py", line 910, in run
self._target(*self._args, **self._kwargs)
File "/Users/tdeveloper/Development/Learning/Python_Simple_WSGI/socket/thread_socketserver.py", line 26, in handle_connection
self._target(*self._args, **self._kwargs)
File "/Users/tdeveloper/Development/Learning/Python_Simple_WSGI/socket/thread_socketserver.py", line 26, in handle_connection
request += conn.recv(1024)
BlockingIOError: [Errno 35] Resource temporarily unavailable
request += conn.recv(1024)
BlockingIOError: [Errno 35] Resource temporarily unavailable
This is apparently an issue with the macos implementation of accept being different than that in other platforms with respect to inheritance of the non-blocking flag. It has nothing to do with threading per se.
Here's a trimmed-down single-threaded test program that demonstrates.
#!/usr/bin/env python3
import select
import socket
ssocket = socket.socket()
ssocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ssocket.bind(('127.0.0.1', 7000))
ssocket.listen(10)
ssocket.setblocking(0) # <<<<<<<===========
select.select([ssocket], [], [])
csocket, caddr = ssocket.accept()
csocket.recv(10)
If you run this on linux, and connect to it with nc localhost 7000, the csocket.recv blocks as you're expecting. Run the same program on macos and the recv immediately triggers the BlockingIOException you're seeing.
Looking at the manual page accept(2) on macos shows:
[...] creates a new socket with the same properties of socket
In this case, the non-blocking file descriptor flag (O_NONBLOCK) is being "inherited" by the new socket. So if you don't want it, you'll need to disable it on the accepted socket with conn.setblocking(1). Apparently this behavior is due to MacOS being descended from the BSD flavor of Unix.
All of that being said, you have no need to disable blocking anyway unless there is more to your actual program than shown. I.e. if your main thread is doing nothing but accepting a connection and then spinning off a separate thread to handle the connection, there's no reason not to let the main thread just block in accept. If you allow the listening socket to remain in blocking mode, the accepted sockets should also be in blocking mode. (By the way, as is, you're wasting a ton of CPU time in that main thread loop: calling accept, trapping the exception, then doing continue to start the loop over.)
(For clarity, my specs: python 3.7.3 downloaded from https://www.python.org/ftp/python/3.7.3/python-3.7.3-macosx10.9.pkg running on MacOS Catalina 10.15.7)
i'm trying to do client-server project. In this project i have to send linux command from client to server. Now i can send some commands like a ls, pwd etc. and they are running correctly and i can read output in client terminal but when i try to send "cd" command, i don't get any error but the directory in server doesn't change. If i use os.chdir(os.path.abspath(data)) command instead of subprocess.check_output , it can change directory but it is useless because i can send a other commands like a ls, pwd , mkdir etc. Thanks for your help
server side:
def threaded(c):
while True:
# data received from client
data = c.recv(1024)
if not data:
print('Bye')
break
try:
data_o = subprocess.check_output(data, shell=True)
except subprocess.CalledProcessError as e:
c.send(b'failed\n')
print(e.output)
if(len(data_o) > 0):
c.send(data_o)
else:
c.send(b'There is no terminal output.')
# connection closed
c.close()
client side:
while True:
# message sent to server
s.send(message.encode('ascii'))
# messaga received from server
data = s.recv(1024)
# print the received message
print('Received from the server :',str(data.decode('ascii')))
# ask the client whether he wants to continue
ans = input('\nDo you want to continue(y/n) :')
if ans == 'y':
message = input("enter message")
continue
else:
break
# close the connection
s.close()
You could check if the command being sent is equal to cd and change the runtime behavior based on that.
data_spl = data.split()
if data_spl[0] == 'cd':
data_o = os.chdir(os.path.abspath(data_spl[1]))
else:
data_o = subprocess.check_output(data, shell=True)
import time
from umqtt.simple import MQTTClient
from machine import Pin
from dht import DHT22
SERVER = 'X.X.X.X' # MQTT Server Address (Change to the IP address of your Pi)
CLIENT_ID = 'ESP32_DHT22_Sensor'
TOPIC = b'temp_humidity'
running = True
client = MQTTClient(CLIENT_ID, SERVER)
client.connect() # Connect to MQTT broker
sensor = DHT22(Pin(15, Pin.IN, Pin.PULL_UP)) # DHT-22 on GPIO 15 (input with internal pull-up resistor)
def run():
while running:
try:
sensor.measure() # Poll sensor
t = sensor.temperature()
h = sensor.humidity()
tm = time.localtime(time.time())
if isinstance(t, float) and isinstance(h, float) and tm[0] > 2000: # Confirm sensor results$
msg = (b'{0:n},{1:n},{2:n},{3:n},{4:n},{5:3.1f},{6:3.1f}'.format(tm[0], tm[1], tm[2]$
client.publish(TOPIC, msg, retain=True) # Publish sensor data to MQTT topic
print(str(msg))
print('Sent to ' + SERVER + ' as ' + CLIENT_ID + '. Exiting.')
running = False
else:
print('Invalid sensor readings.')
except OSError:
print('Failed to read sensor.')
time.sleep(1)
Apologies for importing the whole script. As it is short, I thought it may be valuable to be able to see all of it. I import time at the top of the script and as far as I can tell, all variables are referenced before they are used.
I would like to import this script as dht_publish and then run dht_publish.run(). However, this gives the following error. This is run on the latest MicroPython binary on an ESP32 dev board.
Traceback (most recent call last):
File <stdin>, line 1, in <module>
File dht_publish.py, line 33, in run
NameError: local variable referenced before assignment
If I comment out the time.sleep(1) line then the error is flagged on the line before which suggests that the error may be elsewhere in the code but I can't see where. Any help on this would be very much appreciated.
In case anyone is trying something similar and runs up against the same issue, the problem was that the running variable within the run function was looking up a local variable. Moving the definition of the running variable to the first line after def run(): solved the issue.
im trying to send a message to myself in python but the client code gives me error 10061 the server works properly it worked just fine but than it suddenly started giving me the error. i tried changing the port but it still gives me the same error
the server
from socket import *
from datetime import *
def main():
s = socket()
client_socket = None
s.bind(("127.0.0.1",8200))
print "1:time"
print "2:get list of files"
print "3:download file"
print "4:quit"
input()
s.listen(1)
client_socket, client_address = s.accept()
strn=client_socket.recv(4096)
if int(strn[0])>4 or int(strn[0])<1:
print "please send a num between 1-4"
elif int(strn[0])==1:
print datetime.time(datetime.now())
elif int(strn[0])==2:
folder=raw_input("enter the name of the folder")
dir(folder)
client_socket.close()
s.close()
input()
if name == '__main__':
main()
the client
from socket import *
def main():
s = socket()
s.connect(("127.0.0.1",8200))
buf = raw_input()
s.send(buf)
s.close()
input()
if name == '__main__':
main()
the error
Traceback (most recent call last):
File "D:\client.py", line 10, in <module>
main()
File "D:\client.py", line 4, in main
s.connect(("127.0.0.1",8200))
File "C:\Python27\lib\socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
error: [Errno 10061] No connection could be made because the target machine actively refused it
10061 error occurs when the target machine refuses a connection.
In your case the most likely reason is the "IP" in s.bind and s.connect try putting an actual IP or 127.0.0.1. It should work
never mind i fixed it the problem was that the input was before the listen and it stalled the program thanks everyone
I am attempting to have a python script that constantly monitors a gmail account for new emails. Using IMAPClient, it opens two imap connections, one in idle mode. Whenever a new message is received, the connection in idle mode tells the other connection that it should fetch new mail. The non-idle connection will fetch the mail, perform some processing, then archive the email.
The problem comes when I have many emails arriving in a short period of time, more than a few in a minute. In this case, I get an AssertionError. Below is a minimal example to reproduce the error. In addition to the imap connection, it also opens an smtp connection so that it can send the emails to itself. It will usually fail with the AssertionError at some point after 5-7 emails have been sent. The AssertionError comes in the call to idle_check.
A few short comments on running the code. It does not use OAuth, and so gmail's must be set to allow less secure apps. The "username" and "password" fields at the bottom of the script must be set. The script will also archive any emails that are currently in the inbox, and so it should not be run on a primary email account.
#!/usr/bin/env python3
import smtplib
import imapclient
import email
import threading
import time
class Server(object):
def __init__(self,username,password):
self.username = username
self.password = password
def start(self):
self.stop_running = threading.Event()
self.has_mail = threading.Event()
threading.Thread(target=self._idle).start()
threading.Thread(target=self._poll).start()
print('Listening for messages now')
def _idle(self):
imap_idle = self.imap_connect()
while not self.stop_running.is_set():
imap_idle.idle()
for i in range(600):
try:
if imap_idle.idle_check(1):
self.has_mail.set()
except AssertionError as e:
self.stop_running.set()
raise
imap_idle.idle_done()
imap_idle.noop()
def _poll(self):
imap_poll = self.imap_connect()
self.process_unread(imap_poll)
while True:
if self.has_mail.wait(1):
self.has_mail.clear()
self.process_unread(imap_poll)
if self.stop_running.is_set():
return
def imap_connect(self):
imap = imapclient.IMAPClient('imap.gmail.com',use_uid=True,ssl=True)
imap.login(self.username,self.password)
imap.select_folder('INBOX')
return imap
def process_unread(self, imap):
imap.select_folder('INBOX')
messages = imap.search()
if messages:
imap.copy(messages,'[Gmail]/All Mail')
imap.delete_messages(messages)
def smtp_connect(self):
smtp = smtplib.SMTP('smtp.gmail.com',587)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login(self.username,self.password)
return smtp
def send(self,recipient,subject='',body=''):
headers = ['from: ' + self.username,
'subject: ' + subject,
'to: ' + recipient,
'mime-version: 1.0',
'content-type: text/html']
headers = '\r\n'.join(headers)
self.smtp_connect().sendmail(self.username,recipient,headers+'\r\n\r\n'+body)
def main():
username = 'username#gmail.com'
password = 'password'
s = Server(username, password)
s.start()
for i in range(8):
if s.stop_running.is_set():
break
print('Sending message',i)
s.send(username,
'Test Message'.format(i),
'Body {}'.format(i))
time.sleep(15)
if __name__=='__main__':
main()
The error messsage given is as follows. The text variable at the time of error is sometimes b'XISTS' and sometimes b' FLAGS (\\Seen))'.
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
self.run()
File "/usr/lib/python3.4/threading.py", line 868, in run
self._target(*self._args, **self._kwargs)
File "./emailer.py", line 31, in _idle
if imap_idle.idle_check(1):
File "/path/to/the/venv/lib/python3.4/site-packages/imapclient/imapclient.py", line 519, in idle_check
resps.append(_parse_untagged_response(line))
File "/path/to/the/venv/lib/python3.4/site-packages/imapclient/imapclient.py", line 1093, in _parse_untagged_response
assert text.startswith(b'* ')
AssertionError
I am running this with Python 3.4.0, using IMAPClient 0.13. This is being run in a clean virtualenv, with no other libraries installed. Any assistance would be quite appreciated.