2013-02-28 2 views
1

Я пытаюсь отправить данные из программы C в скрипт python через сокеты, чтобы выполнять визуализацию данных в режиме реального времени с помощью matplotlib. Я также создал графический интерфейс с использованием wxPython. Я использовал модуль сокета, модуль SocketServer и скрутил. В каждом из них у меня были разные проблемы.wxpython server

Используя модуль сокетов, я получал более одного сообщения в сочетании. Я уменьшил размер буфера функции recv(), но тогда я получил только один пакет, а после этого ничего.

Затем я начал использовать скрученный. Я все еще получал пакеты как коллекцию, а не один за другим. Более того, когда задержка была вставлена ​​в файл C, мой скрипт python разбился.

Затем я перешел на SocketServer, и я создал поток для запуска сервера. Сообщения поступали так, как я хотел, но я больше не могу взаимодействовать с графическим интерфейсом.

Все, что я хочу сделать, это отправить строку из 4 значений в скрипт Python, разделить ее и ее графику, с интерактивным пользовательским интерфейсом, и я не могу найти пример взаимодействия сервера, matplotlib и wxPython.

Это код C, что я нашел, и я использую:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <string.h> 
#include <unistd.h> 
#define PORT  9992 
#define HOST  "localhost" 
#define DIRSIZE  8192 

main(argc, argv) 
int argc; char **argv; 
{ 
char hostname[100]; 
char dir[DIRSIZE]; 
int sd; 
struct sockaddr_in sin; 
struct sockaddr_in pin; 
struct hostent *hp; 
char message[50]; 
int i = 0; 
int count = 50; 

strcpy(hostname,HOST); 
if (argc>2) 
{ strcpy(hostname,argv[2]); } 

/* go find out about the desired host machine */ 
if ((hp = gethostbyname(hostname)) == 0) { 
    perror("gethostbyname"); 
    exit(1); 
} 

/* fill in the socket structure with host information */ 
memset(&pin, 0, sizeof(pin)); 
pin.sin_family = AF_INET; 
pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; 
pin.sin_port = htons(PORT); 

/* grab an Internet domain socket */ 
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
    perror("socket"); 
    exit(1); 
} 

/* connect to PORT on HOST */ 
if (connect(sd,(struct sockaddr *) &pin, sizeof(pin)) == -1) { 
    perror("connect"); 
    exit(1); 
} 

/* send a message to the server PORT on machine HOST */ 
while (i < 100){ 
    sprintf(message, "%d %d %d %d \n", count, count + 50, count + 100, count + 130); 
    if (send(sd, message, strlen(message), 0) == -1) { 
     perror("send"); 
     exit(1); 
    } 
    count = count + 50; 
    i++; 
    sleep(1); 
} 


shutdown (sd, 2); 
} 

И это код Python, что я в настоящее время (после поиска по всей сети):

class ThreadedEchoRequestHandler(SocketServer.StreamRequestHandler): 

def handle(self): 
    cur_thread = threading.currentThread() 
    line = self.rfile.readline() 
    while True: 
     line = self.rfile.readline() 
     if not line: break 
     print "%s wrote: %s" % (self.client_address[0], line.rstrip()) 
     self.wfile.write(line) 
    return 

class ThreadedEchoServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 
    pass 
######################################################################################## 
class MyFrame(wx.Frame): 
def __init__(self, parent, title): 
    wx.Frame.__init__(self, parent, -1, title, size=(1024,768)) 

    self.SetIcon(wx.Icon('sim.ico', wx.BITMAP_TYPE_ICO)) 
    self.SetBackgroundColour('#ece9d8') 

    self.add_toolbar() 
    self.Centre() 

    #Flag variables 
    self.isLogging = False 
    self.threads = [] 
    server = ThreadedEchoServer(('localhost',9997), ThreadedEchoRequestHandler) 
    t = threading.Thread(target=server.serve_forever) 
    t.start() 

    #Create data buffers 

    #Some GUI Design Code 

    #Create timer to read incoming data and scroll plot 

    #Create start/stop button 
    self.start_stop_button = wx.Button(self, label="Start", pos=(80,550), size=(150,150)) 
    self.start_stop_button.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)) 
    self.start_stop_button.Bind(wx.EVT_BUTTON, self.onStartStopButton) 

def add_toolbar(self): 
    # Toolbar code 

def onStartStopButton(self, event): 
    if not self.isLogging: 
     self.isLogging = True 
     self.start_stop_button.SetLabel("Stop") 
     call(["/home/user/Misc/socketTest/socketTest"]) 
    else: 
     self.isLogging = False 
     self.start_stop_button.SetLabel("Start")     

def GetSample(self, msg): 
### Manipulate Data from socket for matplotlib update 

if __name__ == '__main__': 
    app =wx.App(False) 
    frame = MyFrame(None, 'Sim') 
    frame.Show(True) 
    app.MainLoop() 

Извините, но я новичок в Python. Заранее спасибо.

+0

Это очень сложная проблема, есть ли в любом случае вы можете разбить ее на более мелкие, понятные/адресные куски? – tacaswell

+0

Я не понимаю, что вы имеете в виду. Я думаю, что мой сервер находится в другом потоке, поэтому gui не должен быть затронут. Но это так. Извините, но я не знаком с Python. – user2117698

+0

Если вы считаете, что это в первую очередь проблема с потоками/wx, то вычеркивайте весь код «matplotilb», чтобы было легче увидеть, что происходит. Вы получите больше и больше ответов с вопросом, который включает _only_ код, который имеет отношение к воспроизведению вашей проблемы. – tacaswell

ответ

0

Я не могу сказать, какой лучший подход к сокет-коммуникациям, это действительно зависит от потребностей вашего приложения, типа и формата передаваемых данных, объема и т. Д. Но я могу помочь с интеграцией с графическим интерфейсом.

Существует несколько ключевых принципов, которые следует учитывать при добавлении таких приложений, как услуги сокетов, в приложение GUI. Во-первых, чтобы пользовательский интерфейс реагировал на пользователя, вы не должны ничего делать в обработчиках событий UI или других обратных вызовах, которые могут блокировать «заметное» время пользователя. Во-вторых, вы не должны делать ничего, что создает или манипулирует любыми элементами GUI из потока, отличного от потока пользовательского интерфейса.

Так что ваш инстинкт запускать SocketServer (или все, что вы в конечном итоге используете) из другого потока является хорошим. Это позволяет вам уделять пристальное внимание потоку обработке сообщений и не иметь дело с более сложными вещами, такими как периодический опрос, получение обработки событий пользовательского интерфейса и т. Д. Он может просто заблокировать ожидание входящих данных.

Существует несколько методов, которые могут использоваться для передачи входящих данных из сокета в поток пользовательского интерфейса. Вероятно, проще всего использовать функцию wx.CallAfter wxPython. Он позволяет указать какой-то вызываемый объект, который должен быть вызван, и параметры, которые должны быть переданы ему, а затем он вызовет этот вызов в ближайшее время в контексте потока пользовательского интерфейса.

+0

Да, но проблема в том, что мой графический интерфейс блокируется, хотя я запускаю свой сервер в другом нить. Я не могу взаимодействовать с графическим интерфейсом, и мой сервер работает в фоновом режиме ... – user2117698

+0

Является ли связанный с сервером потоком? Это может привести к тому, что поток пользовательского интерфейса станет голодным для циклов. Если вы сделаете небольшой runnable образец, который демонстрирует проблему, это будет легче помочь. Если вы разместите его в списке пользователей wxPython, вы, вероятно, получите много помощи. http://wiki.wxpython.org/MakingSampleApps – RobinDunn