2013-02-28 2 views
1

matplotlib를 사용하여 데이터를 실시간으로 시각화하기 위해 C 프로그램에서 파이썬 스크립트로 소켓을 통해 데이터를 보내려고합니다. 또한 wxPython을 사용하여 GUI를 만들었습니다. 소켓 모듈, SocketServer 모듈을 사용하고 꼬아 서 사용했습니다. 각자 다른 문제가있었습니다.wxpython 서버

소켓 모듈을 사용하여 하나 이상의 메시지가 결합되었습니다. 나는 recv() 함수의 버퍼 크기를 줄 였지만 그때는 하나의 패키지 만 얻고 그 이후에는 아무 것도 얻지 못했습니다.

그럼 트위스트를 사용하기 시작했습니다. 나는 꾸러미를 하나씩 수집하는 것이 아니라 아직도 꾸러미를 얻고 있었다. 또한 C 파일에 지연이 삽입되면 python 스크립트가 충돌합니다.

그런 다음 SocketServer로 이동하고 서버를 실행하는 스레드를 만들었습니다. 내가 원한대로 메시지가 나오지만 더 이상 GUI와 상호 작용할 수 없습니다.

필자가 원하는 것은 Python 스크립트에 문자열 4 개를 보내고 스트립과 플롯을 만들고 대화식 UI가 있고 서버, 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); 
} 

을 그리고 이것은 (그물을 모두 검색 한 후) 내가 현재 가지고있는 파이썬 코드 :

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() 

미안하지만 파이썬을 처음 접 하네. 미리 감사드립니다.

+0

이것은 매우 복잡한 문제입니다. 어쨌든 작고 이해하기 쉽도록/청크 주소를 구분할 수 있습니까? – tacaswell

+0

무슨 뜻인지 이해할 수 없습니다. 나는 내 서버가 다른 스레드에있어 GUI가 영향을받지 않아야한다고 생각한다. 하지만 그렇습니다. 죄송 합니다만 파이썬에 익숙하지 않습니다. – user2117698

+0

이것이 주로 스레딩/wx 문제라고 생각한다면,'matplotilb' 코드를 모두 없애면 무슨 일이 일어나는지 쉽게 알 수 있습니다. 문제를 재현하는 데 관련된 코드 만 포함하는 질문을 통해 더 많은 답변을 얻을 수 있습니다. – tacaswell

답변

0

소켓 통신에 가장 적합한 방법이 무엇인지 말할 수는 없지만 응용 프로그램의 요구, 전송되는 데이터의 형식과 형식, 볼륨 등에 따라 달라집니다.하지만 통합에 도움이 될 수 있습니다. GUI 응용 프로그램으로.

GUI 응용 프로그램에 소켓 서비스와 같은 것을 추가 할 때주의해야 할 몇 가지 핵심 원칙이 있습니다. 첫째, 사용자가 UI를 응답하도록 유지하려면 UI 이벤트 핸들러 또는 "사용자 눈에 띄는"시간 동안 차단 될 수있는 다른 콜백에서 어떤 작업도해서는 안됩니다. 둘째, UI 스레드가 아닌 다른 스레드에서 GUI 요소를 생성하거나 조작하는 작업을해서는 안됩니다.

그래서 다른 스레드에서 SocketServer (또는 결국 사용하는 모든 것)를 실행하는 본능이 좋습니다. 이를 통해 스레드는 통신을 처리하고주기적인 폴링, UI 이벤트 처리에 대한 항복 등과 같은 더 복잡한 작업을 처리 할 필요가 없다는 점에주의를 기울일 수 있습니다. 들어오는 데이터를 기다리는 것을 막을 수 있습니다.

들어오는 데이터를 소켓에서 UI 스레드로 전달하는 데 사용할 수있는 몇 가지 방법이 있습니다. 아마도 가장 쉬운 방법은 wxPython의 wx.CallAfter 함수를 사용하는 것입니다. 호출해야하는 호출 가능 객체와 전달할 매개 변수를 지정할 수 있습니다. 그런 다음 UI 스레드의 컨텍스트에서 곧 호출이 발생합니다.

+0

예,하지만 문제는 제 GUI가 다른 서버에서 실행되지만 차단됩니다. 실. GUI와 상호 작용할 수없고 내 서버는 백그라운드에서 계속 실행됩니다 ... – user2117698

+0

서버 스레드가 CPU 바인딩되어 있습니까? 이로 인해 UI 스레드가 주기적으로 멈출 수 있습니다. 문제를 보여주는 작은 실행 가능한 샘플을 만들면 도움이 될 것입니다. wxPython 사용자 목록에 게시하면 많은 도움을받을 수 있습니다. http://wiki.wxpython.org/MakingSampleApps – RobinDunn