I haven't been doing almost any programming before this so I apologize in advance for the quality of my code.
The problem I'm having is that I have a GUI and I need to open a server to receive internet traffic, but if I try to open it in a new process I get an error about a name not being defined (even though it works just fine if I open the server as a regular function and not a new process). The funny thing is that the GUI still opens even though I get the error.
I'll paste the error messages after the code.
Thank you in advance.
from Tkinter import *
import socket, re
import netifaces as ni
from multiprocessing import Process, Manager
class Application(Frame):
def __init__(self, master):
""" Initialize the Frame"""
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.label1 = Label(text = "Target IPv6 address")
self.label1.grid(row=1, column=0)
self.entry1 = Entry(bd = 5)
self.entry1.grid(row=1, column = 1)
self.button1 = Button(text = "Start", command = self.clientstart)
self.button1.grid(row=1, column = 2)
pr1 = Process(target=self.serverstart)
self.button2 = Button(text = "Start", command = pr1.start())
self.button2.grid(row=2, column=2)
self.label2 = Label(text = "Choose interface to listen")
self.label2.grid(row=2, column=0)
self.interfaces = Menubutton(text="------", relief=RAISED)
self.interfaces.grid(row=2, column=1)
self.interfaces.menu = Menu(self.interfaces, tearoff=0)
self.interfaces["menu"] = self.interfaces.menu
self.menubox()
def menubox(self):
self.interfaces.menu.add_command(label="------", command = lambda interface="------": self.callback(interface))
for interface in ni.interfaces():
if interface.startswith('eth'):
self.interfaces.menu.add_command(label=interface, command = lambda interface=interface: self.callback(interface))
else:
pass
def callback(self, interface):
if interface.startswith('eth'):
self.interfaces["text"] = interface
else:
self.interfaces["text"] = "------"
self._netint = interface
def serverstart(self):
import tcpServer
tcpServer.start(self._netint)
def clientstart(self):
targetip = self.entry1.get()
import tcpClient
tcpClient.startclient(targetip)
root = Tk()
root.title("IPv6 traffic generator")
root.geometry("400x600")
app = Application(root)
root.mainloop()
Process Process-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "gui.py", line 57, in serverstart
tcpServer.start(netint)
NameError: global name 'netint' is not defined
EDIT:
I tried the advice in the first reply, but it still gives an error
Process Process-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "gui.py", line 55, in serverstart
tcpServer.start(self._netint)
AttributeError: Application instance has no attribute '_netint'
Here is the code for tcpServer.py
import socket
import netifaces as ni
def start(self, _netint):
host = ni.ifaddresses(self._netint)[ni.AF_INET6][0]['addr']
port = 5000
s = socket.socket(socket.AF_INET6)
s.bind((host, port))
s.listen(1)
c, addr = s.accept()
print "Connection from: " + str(addr)
while True:
data = c.recv(1024)
if not data:
break
print "from connected user: " + str(data)
data = str(data).upper()
print "sending: " + str(data)
c.send(data)
c.close()
if __name__ == '__main__':
start()
And here for tcpClient.py
import socket
def startclient(targetip):
host = targetip
port = 5000
s = socket.socket(socket.AF_INET6)
s.connect((host,port))
message = raw_input('Send message: ')
while message != 'q':
s.send(message)
data = s.recv(1024)
print 'Recieved from server: ' + str(data)
message = raw_input('Send message: ')
s.close()
if __name__ == '__main__':
startclient()
Please note that my server and client programs are just for testing for now.
I can't actually run your code to check, but it looks like the error can be fixed like this:
def callback(self, interface):
if interface.startswith('eth'):
self.interfaces["text"] = interface
else:
self.interfaces["text"] = "------"
self._netint = interface
def serverstart(self):
import tcpServer
tcpServer.start(self._netint)
Generally, it's best to avoid using global as much as possible. One of the benefits of using classes is that it provides a shared namespace that all the methods of class instances can access via self.
Related
first time questioner here!
I´m currently working on a python project that´s supposed to read soil moisture through a sensor on a raspberry pi, which then sends the data to another laptop through a socket connection. That other laptop displays the data in a UI. That UI is also capable of controllig the script flow. My Server starts up just fine, but when the client connects to it(connection itself works), I get the following Error Stack:
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/usr/lib/python3.5/threading.py", line 862, in run
self._target(self._args, **self._kwargs)
File "/home/pi/Py_Scripts/MoistureSensor/Server.py", line 77, in worker_recv
self.JSON_Control = pickle.loads(self.data_recv)
EOFError: Ran out of input
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/usr/lib/python3.5/threading.py", line 862, in run
self._target(self._args, **self._kwargs)
File "/home/pi/Py_Scripts/MoistureSensor/Server.py", line 70, in worker_send
self.conn.send(self.data_send)
BrokenPipeError: [Errno 32] Broken pipe
My Scripts look as follows:
Client-side:
import sys
from socket import *
from threading import Thread
from time import sleep
import pickle
from PySide6 import QtWidgets, QtGui
class MyClient:
def __init__(self, server_port, buf_size, host):
self.server_port = server_port
self.buf_size = buf_size
self.host = host
self.data_send = None
self.data_recv = None
self.exit = False
self.JSON_Control = {
"measure": False,
"exit": False,
}
self.JSON_Moisture = {
"moisture_level": 0
}
self.socket_connection = socket(AF_INET, SOCK_STREAM)
self.socket_connection.connect((self.host, self.server_port))
print("Connected with Server: %s: " % self.host)
# thread for sending
self.thread_send = Thread(target=self.worker_send)
# thread for receiving
self.thread_recv = Thread(target=self.worker_recv)
# starting Threads
self.thread_send.start()
self.thread_recv.start()
def worker_send(self):
while not self.exit:
self.data_send = pickle.dumps(self.JSON_Control)
self.socket_connection.send(self.data_send)
sleep(0.5)
def worker_recv(self):
while not self.exit:
self.data_recv = self.socket_connection.recv(self.buf_size)
if self.data_recv is not None:
self.JSON_Moisture = pickle.loads(self.data_recv)
class UiDisplay(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.moisture_label = None
self.moisture_level = None
self.start_button = None
self.refresh_button = None
self.stop_button = None
self.reset_button = None
self.quit_button = None
self.create_widgets()
def create_widgets(self):
# create a label to display the current time
self.moisture_label = QtWidgets.QLabel(self)
self.moisture_label.setFont(QtGui.QFont("Helvetica", 16))
self.moisture_level = client.JSON_Moisture["moisture_level"]
self.moisture_label.setText('Bodenfeuchtigkeit: ' + str(self.moisture_level)[:3] + '%')
# button to start the weight measuring
self.start_button = QtWidgets.QPushButton("Start measuring", self)
self.start_button.clicked.connect(self.measure_moisture)
# button to refresh the Weight label
self.refresh_button = QtWidgets.QPushButton("Refresh", self)
self.refresh_button.clicked.connect(self.refresh)
# button to stop measuring
self.stop_button = QtWidgets.QPushButton("Stop measuring", self)
self.stop_button.clicked.connect(self.stop_measuring)
# button to quit the program
self.quit_button = QtWidgets.QPushButton("Quit", self)
self.quit_button.clicked.connect(self.quit)
# create a layout to hold the widgets
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.moisture_label)
layout.addWidget(self.start_button)
layout.addWidget(self.refresh_button)
layout.addWidget(self.stop_button)
layout.addWidget(self.reset_button)
layout.addWidget(self.quit_button)
self.setLayout(layout)
def measure_moisture(self):
client.JSON_Control["measure"] = True
def refresh(self):
# get current weight ( niederlag auf ein qm rechnen fehlt noch)
self.moisture_level = round(client.JSON_Moisture["moisture_level"] - 2.7) / (1 - 2.7)
print(self.moisture_level)
# umrechnen von analogem Wert zu Prozentanteil
print(self.moisture_level)
# update the weight label with the current time
self.moisture_label.setText('Bodenfeuchtigkeit: ' + str(self.moisture_level)[:5] + '%')
def stop_measuring(self):
if client.JSON_Control["measure"]:
client.JSON_Control["measure"] = False
else:
pass
def quit(self):
QtWidgets.QApplication.instance().quit()
client.JSON_Control["exit"] = True
sleep(2)
client.exit = True
client.thread_recv.join()
client.thread_send.join()
client.socket_connection.close()
print("Server connection is closed")
print('exiting...')
sleep(1)
sys.exit()
client = MyClient(1957, 1024, "192.168.86.121")
app = QtWidgets.QApplication()
window = UiDisplay()
window.show()
app.exec()
--------------------------------------------------------
The Server-side:
import sys
from socket import *
from threading import Thread
import pickle
from time import sleep
import Adafruit_ADS1x15
adc_channel_0 = 0
class SoilMoistureSensor:
def __init__(self, gain, sps, dry_voltage, saturated_voltage):
self.adc = Adafruit_ADS1x15.ADS1115()
self.raw_data = None
self.moisture_level = None
# self.voltage = None
self.gain = gain
self.sps = sps
self.dry_voltage = dry_voltage
self.saturated_voltage = saturated_voltage
class MyServer:
def __init__(self, echo_port, buf_size):
self.buf_size = buf_size
self.echo_port = echo_port
self.data_send = None
self.data_recv = None
self.exit = False
self.data_json = None
self.moisture_sensor = SoilMoistureSensor(2, 32, 1, 2.7) # gain, sps, saturated_voltage, dry_voltage
self.JSON_Control = {
"measure": False,
"exit": False
}
self.JSON_Moisture = {
"moisture_level": 0,
}
self.socket_connection = socket(AF_INET, SOCK_STREAM)
self.socket_connection.bind(("", self.echo_port))
self.socket_connection.listen(1)
print("Server gestartet")
print("Name des Hosts: ", gethostname())
print("IP des Hosts: ", gethostbyname(gethostname()))
self.conn, (self.remotehost, self.remoteport) = self.socket_connection.accept()
print("Verbunden mit %s %s " % (self.remotehost, self.remoteport))
# thread for sending
self.thread_send = Thread(target=self.worker_send)
# thread for receiving
self.thread_recv = Thread(target=self.worker_recv)
# thread for checking Json Control
self.thread_check_json_control = Thread(target=self.check_json_control)
# starting Threads
self.thread_send.start()
self.thread_recv.start()
self.thread_check_json_control.start()
def worker_send(self):
while not self.exit:
self.data_send = pickle.dumps(self.JSON_Moisture)
self.conn.send(self.data_send)
sleep(0.5)
def worker_recv(self):
while not self.exit:
self.data_recv = self.conn.recv(self.buf_size)
if self.data_recv is not None:
self.JSON_Control = pickle.loads(self.data_recv)
def measure_moisture(self, channel):
channel = adc_channel_0
self.moisture_sensor.raw_data = self.moisture_sensor.adc.read_adc(
channel, self.moisture_sensor.gain, self.moisture_sensor.sps)
self.JSON_Moisture["moisture_level"] = self.moisture_sensor.raw_data
print(self.moisture_sensor.raw_data)
def stop_connection(self):
self.thread_recv.join()
self.thread_send.join()
self.thread_check_json_control.join()
self.socket_connection.close()
print("Server connection is closed")
print('exiting...')
sys.exit()
def check_json_control(self):
while not self.exit:
if self.JSON_Control["measure"]:
self.measure_moisture(0)
if self.JSON_Control["exit"]:
self.stop_connection()
sleep(0.5)
server = MyServer(1957, 1024)
I´d be ever so grateful for help and I´m incredibly sorry if I´ve disregarded any question conventions. Cheers!
I have a customtkinter (CTk) button widget that, when pressed, sends an encoded message to a client depending on the button's "text" value; in this case, if the button's text is "Off", it sends the message "On" and vice versa to the client.
import tkinter as tk
import traceback
import customtkinter as cust
import socket
from threading import Thread
from tkinter import messagebox
class GUI2(cust.CTk): #second window; not the root
def __init__(self):
super().__init__()
self.PORT = 5000
self.SERVER = socket.gethostbyname(socket.gethostname())
self.ADDRESS = (self.SERVER, self.PORT)
self.FORMAT = "utf-8"
self.clients = [] #list to store all client connections
self.server = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
self.server.bind(self.ADDRESS)
self.master2 = cust.CTkToplevel()
self.ecdpower = cust.CTkButton(self.master2, text = "Off", fg_color = "Black", text_color = "White", hover_color = "Silver", command = lambda: Thread(target = self.startstream).start())
self.ecdpower.grid(row = 0, column = 0) #button to send message to client connections
self.thread = Thread(target = self.startChat)
self.thread.start() #starts function to accept client connections
def startChat(self): #function to accept client connections
self.server.listen(30)
try:
while True:
self.conn, self.addr = self.server.accept()
self.clients.append(self.conn) #stores all client connections
except:
pass
def startstream(self):
try:
if not self.clients: #checks if list is empty
messagebox.showerror("No Connections!", "No clients connected to host!")
else:
for x in self.clients:
if self.ecdpower["text"] == "Off": #ecdpower button widget acts like a "power button"
self.ecdpower.configure(text = "On", fg_color = "Green")
x.send(("On").encode(self.FORMAT))
else:
self.ecdpower.configure(text = "Off", fg_color = "Red")
x.send(("Off").encode(self.FORMAT))
except:
print (traceback.format_exc())
Error is as follows:
Traceback (most recent call last):
File "f:\project\mainmenu.py", line 390, in startstream
File "F:\Program Files (x86)\Python\lib\tkinter\__init__.py", line 1681, in cget
return self.tk.call(self._w, 'cget', '-' + key)
_tkinter.TclError: unknown option "-text"
I have also tried if self.ecdpower.cget("text") == "Off: and tried other values like fg_color; both result in the same error. When I removed the if condition, the message sending works correctly so the only problem is how to verify the button "text" value.
Any help to fix this or possible other alternatives is greatly appreciated.
Per #jasonharper's comment above, CTkButton is
not actually a Tkinter Button at all (it's made from a Frame containing a Canvas and a Label), so the normal Tkinter attribute-getting functions don't apply.
Instead of using self.ecdpower["text"] or self.ecdpower.cget("text"): I should use
self.ecdpower.text
to get the CTKbutton's text value.
The same can be applied with fg_color; use self.ecdpower.fg_color to get the value.
ErrorLog:
File "???\Python\Python38\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "???\Python\Python38\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "main.py", line 27, in th_listen_user
content = data.split('\n'.encode('utf-8'))[3]
IndexError: list index out of range
ServerCode:
import socket
import threading as th
server = socket.socket(
socket.AF_INET,
socket.SOCK_STREAM
)
server.bind(('127.0.0.1',8000))
server.listen(100)
USERS = {}
Exit = 0
def th_listen_user(user,adress):
try:
while True:
data = user.recv(2048)
ip = data.split('\n'.encode('utf-8'))[0].decode('utf-8')
port = int(data.split('\n'.encode('utf-8'))[1].decode('utf-8'))
part = data.split('\n'.encode('utf-8'))[2]
content = data.split('\n'.encode('utf-8'))[3]
print(data.split('\n'.encode('utf-8'))) #check Log
print(data)
print(ip,port,part,content)
except ConnectionResetError:print(f'<{adress[0]}:{adress[1]}> DISCONNECTED')
def start_server():
global Exit
while Exit==0:
user_socket,adress = server.accept()
print(f'<{adress[0]}:{adress[1]}> CONNECTED')
USERS[adress] = user_socket
th_func = th.Thread(target = th_listen_user,args = (user_socket,adress))
th_func.start()
print(USERS)
Log:
[b'127.0.0.1', b'9001', b'1', b'gAAAAABhitL94rJt4tAINg5Y1av_hY7YitgnrJD12pgNev6gjomZcYam9_VYQOZIR3Hyg-4mmPAyCKON2JZ3PSG9FHcQZLM_IyJZTAgFexlKc6UG1oVIBCo=']
b'127.0.0.1\n9001\n1\ngAAAAABhitL94rJt4tAINg5Y1av_hY7YitgnrJD12pgNev6gjomZcYam9_VYQOZIR3Hyg-4mmPAyCKON2JZ3PSG9FHcQZLM_IyJZTAgFexlKc6UG1oVIBCo='
127.0.0.1 9001 b'1' b'gAAAAABhitL94rJt4tAINg5Y1av_hY7YitgnrJD12pgNev6gjomZcYam9_VYQOZIR3Hyg-4mmPAyCKON2JZ3PSG9FHcQZLM_IyJZTAgFexlKc6UG1oVIBCo='
I am writing a chat application. There was a problem with the server. He swears at a non-existent mistake.
The error is displayed after the code is executed without errors.
And as I understand it, it is somehow connected with sockets.
What does this error mean and how to avoid it ?
Just to give some context: I'm currently learning Python and to do so I started a little Project.
I wrote two Python Scripts: a Host and a Client script.
I'm already at the point where multiple Clients can connect to one "Host" and the Host can send a random String to all Clients.
Now I wanted to solve the problem, that if a Client disconnects from the Host nobody knows until the CLIENTSOCKET is called again.
So I wrote the checkConnection method to ping all Clients every 5 sec, for now.
class Connection():
def __init__(self):
self.s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
def bound(self,RHOST,PORT):
self.s.bind((RHOST,PORT))
self.s.listen(1000)
def connect(self):
((CLIENTSOCKET,ADRESS)) = self.s.accept()
return (CLIENTSOCKET,ADRESS)
def newConnection(Connection,CLIENTS):
con = Connection
cli = CLIENTS
while True:
c = con.connect()
if c != None:
if len(cli) != 0:
for x in range (len(cli)):
if c[1][0] == cli[x][1][0]:
pass
else:
cli.append(c)
else:
cli.append(c)
def checkConnection(CLIENTS):
cli = CLIENTS
while True:
if(len(cli)!=0):
for x in range(len(cli)):
try:
cli[x][0].sendall(b'')
except:
del cli[x]
time.sleep(5)
I'm creating to Threads with each method as a target and give them the needed parameters. The first thread starts like it should, but the second doesn't.
I really don't know why?
t = threading.Thread(target = newConnection,name = "newConnection",args = (g,CLIENTS))
t2 = threading.Thread(target = checkConnection,name = "checkConnection",args = (CLIENTS))
t.start()
t2.start()
Exception in thread checkConnection:
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python35-32\lib\threading.py", line 914, in _bootstrap_inner
self.run()
File "C:\Users\User\AppData\Local\Programs\Python\Python35-32\lib\threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
TypeError: checkConnection() missing 1 required positional argument: 'CLIENTS'
I have made a chat server client but when I run it I get this error:
Traceback (most recent call last):
File "C:/Users/Public/Documents/Programming/Chat Client/Chat Client.py", line 21, in
<module>
s = socket.socket((socket.AF_INET, socket.SOCK_STREAM))
AttributeError: type object 'socket' has no attribute 'socket'
I don't see the problem so can anyone help me, here is my code:
# Import Modules
from tkinter import *
from socket import *
from threading import *
# Window Setup
root = Tk()
root.title('Chat Client')
root.state('zoomed')
# Chat Variables
global s
s = socket.socket((socket.AF_INET, socket.SOCK_STREAM))
s.connect((TARGET, DEFAULT_PORT))
enter = StringVar()
TARGET = s.gethostname()
DEFAULT_PORT = 45000
# Chat Message Box Setup
chat = Text(root, height=31, state=DISABLED)
entry = Entry(root, fg='blue', textvariable=enter, width=200)
scroll = Scrollbar(root)
chat['yscrollcommand'] = scroll.set
scroll['command'] = chat.yview
scroll.pack(side=RIGHT, fill=Y)
chat.pack(side=TOP, fill=X)
entry.pack(side=BOTTOM)
# Send Command
def send(event):
msg = enter.get()
chat['state'] = NORMAL
chat['fg'] = 'blue'
chat.insert(END, ('You: ' + msg + '\n'))
while 1:
s.sendall(msg)
chat['state'] = DISABLED
chat['fg'] = 'black'
enter.set('')
s.close()
entry.bind('<Return>', send)
def recieve():
s.bind((TARGET, DEFAULT_PORT))
s.listen(True)
conn, addr = s.accept()
while True:
data = conn.recv(1024)
chat['state'] = NORMAL
chat['fg'] = 'red'
chat.insert(END, ('Stranger: ' + data + '\n'))
thread.start(recieve, ())
thread.start(send, ())
root.mainloop()
I am not sure what is wrong with my code so could anyone please help me?
Thanks In Advance!
from socket import *
You've imported the entire socket module. There is no socket.socket. You've imported the socket object directly into the current namespace.
To access it, simple do
s = socket((socket.AF_INET, socket.SOCK_STREAM))
If you had done
import socket
Then you could access the socket object via the module namespace.