Idioma:
English
En esta página
GUI
Código cliente
Código servidor
Gracias
Temas
GIOChannel
Gio.IOChannel
FIFO chat
Socket chat
El programa brinde lo siguiente:
NOTAS:
#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 8 -*-
#
# main.py
# Copyright (C) 2019 John Coppens <john@jcoppens.com>
#
# test_multi is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# test_multi is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib, Gio
import os, sys
import pdb
import socket
import fcntl
import subprocess as sp
UI_FILE = "test_multi.ui"
RTC_DEV = "/dev/rtc0"
IP = "127.0.0.1"
PORT = 9999
XTERM = "xterm"
RTC_UIE_ON = 0x00007003
class RTC():
""" RTC connects a handler to the RTC device (normally /dev/rtc0)
<callback> parameter if defined, will be called on each tick
<viewer> parameter if defined, must be a Gtk.TextView, and a
character will be inserted on each tick
NOTE: At the moment, the 'tick' signal is the default 1 second period.
The rate can be changed with ioctl commands, but this is NOT
implemented here for simplicity.
"""
def __init__(self, parent, viewer = None, callback = None):
self.parent = parent
self.callback = callback
self.viewer = viewer
self.rtc = open(RTC_DEV, "rb")
if not self.rtc:
print("Can't open file:", RTC_DEV)
exit(1)
self.ioch = GLib.IOChannel.unix_new(self.rtc.fileno())
# Datos leidos del RTC son del tipo 'long': No son caracteres validos
# y es preciso de deshabilitar la codificacion:
self.ioch.set_encoding(None)
GLib.io_add_watch(self.ioch, GLib.IO_IN, self.read)
self.enable_interrupts()
def read(self, ioch, par2):
try:
data = self.ioch.read(8) # Cada 'long' tiene 8 bytes
self.append_text("@")
except Exception as e:
print(e)
print("Data read contains strange things")
return True
def enable_interrupts(self):
r = fcntl.ioctl(self.rtc, RTC_UIE_ON, 0)
if r == -1:
print("Could not enable interrupts")
def append_text(self, txt):
if self.callback != None:
self.callback(txt)
bff = self.viewer.get_buffer()
bff.insert(bff.get_end_iter(), txt)
def disable_interrupts(self):
fcntl.ioctl(self.rtc, RTC_UIE_OFF, 0);
class TCP_client():
""" The TCP client tries to connect to the server on instantiation of the
class. So the server must be running!
<callback> parameter if defined, will be called with the data
received on the TCP port.
<viewer> parameter if defined, must be a Gtk.TextView, and
will be updated with the received data.
semd method can be called to send a message to the
TCP port
"""
def __init__(self, host, port,
callback = None,
viewer = None):
self.callback = callback
self.viewer = viewer
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((host, port))
self.socket.setblocking(False)
self.fd = self.socket.fileno() # Obtener el file descriptor
print("Connected to {}".format(host))
GLib.io_add_watch(self.fd, GLib.IO_IN, self.process_input)
# Instalar la funcion en caso
# de datos recibidos
def process_input(self, skt, cond):
""" This function is called asynchronously when data is received.
"""
msg = self.socket.recv(100) # Recibir el mensage de la red
if self.callback != None:
self.callback(msg)
bff = self.viewer.get_buffer()
bff.insert(bff.get_end_iter(), msg.decode("latin-1"))
return True # Queremos quedar activos
def send(self, msg):
self.socket.send(msg.encode("latin-1"))
class GUI:
def __init__(self):
self.builder = Gtk.Builder()
self.builder.add_from_file(UI_FILE)
self.builder.connect_signals(self)
main_window = self.builder.get_object("MainWindow")
# Make an dictionary of references to widgets we are interested in
# from the UI file
self.obj = {}
for objref in ["from_RTC_buffer",
"from_RTC_view",
"from_socket_buffer",
"from_socket_view"]:
self.obj[objref] = self.builder.get_object(objref)
self.rtc = RTC(self,
viewer = self.obj["from_RTC_view"],
callback = self.process_rtc)
self.tcp = TCP_client(IP, PORT,
viewer = self.obj["from_socket_view"],
callback = self.process_tcp)
self.tcp.send("Simulated server (netcat) \n")
main_window.show_all()
def on_window_destroy(self, window):
Gtk.main_quit()
def process_rtc(self, data):
""" Execute anything which has to be synced with the RTC
"""
print(data)
return True
def process_tcp(self, data):
""" Process the data coming from the server
"""
print(data)
return True
def kbd_entry_activate_cb(self, entry):
""" Send the data from the keyboard to the server (and print
on the terminal
"""
text = entry.get_text()
print(text)
self.tcp.send(text + "\n")
entry.set_text('')
def main():
sp.Popen([XTERM, '-e', 'nc', '-l', '-p', '9999'])
gui = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
<?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.20.0 --> <interface> <requires lib="gtk+" version="3.0"/> <object class="GtkTextBuffer" id="from_RTC_buffer"/> <object class="GtkTextBuffer" id="from_kbd_buffer"/> <object class="GtkTextBuffer" id="from_socket_buffer"/> <object class="GtkWindow" id="MainWindow"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="title" translatable="yes">window</property> <property name="default_width">500</property> <property name="default_height">400</property> <signal name="destroy" handler="on_window_destroy" swapped="no"/> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_left">4</property> <property name="margin_right">4</property> <property name="margin_top">4</property> <property name="margin_bottom">4</property> <property name="orientation">vertical</property> <child> <object class="GtkFrame" id="from_RTC"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_top">2</property> <property name="margin_bottom">2</property> <property name="label_xalign">0.05000000074505806</property> <property name="shadow_type">none</property> <child> <object class="GtkAlignment"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="left_padding">12</property> <child> <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="shadow_type">in</property> <child> <object class="GtkTextView" id="from_RTC_view"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="wrap_mode">char</property> <property name="buffer">from_RTC_buffer</property> </object> </child> </object> </child> </object> </child> <child type="label"> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="label" translatable="yes">From RTC</property> </object> </child> </object> <packing> <property name="expand">True</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> <object class="GtkFrame" id="from_kbd_frame"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_top">2</property> <property name="margin_bottom">2</property> <property name="vexpand">False</property> <property name="label_xalign">0.05000000074505806</property> <child> <object class="GtkAlignment"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="left_padding">12</property> <child> <object class="GtkEntry" id="kbd_entry"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="has_focus">True</property> <signal name="activate" handler="kbd_entry_activate_cb" swapped="no"/> </object> </child> </object> </child> <child type="label"> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="label" translatable="yes">From keyboard</property> </object> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <object class="GtkFrame" id="from_socket_frame"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="margin_top">2</property> <property name="margin_bottom">2</property> <property name="label_xalign">0.05000000074505806</property> <child> <object class="GtkAlignment"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="left_padding">12</property> <child> <object class="GtkTextView" id="from_socket_view"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="wrap_mode">char</property> <property name="buffer">from_socket_buffer</property> </object> </child> </object> </child> <child type="label"> <object class="GtkLabel"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="label" translatable="yes">From socket</property> </object> </child> </object> <packing> <property name="expand">True</property> <property name="fill">True</property> <property name="position">2</property> </packing> </child> </object> </child> </object> </interface>
(c) John Coppens ON6JC/LW3HAZ | correo |