2012-03-15 30 views
5

私はアプリケーションサーバー(server.py)とC++をクライアント(client.exe)として持っています。 Client.exeは 'named pipes'を介して変数をserver.pyに送信します。C++からPythonへの通信(IPC)

問題は、server.pyのclient.exeから「クライアントからのデフォルトメッセージ」を送信すると、「D」(最初の文字送信のみ)が生成されます。

誰でも私を助けることができますか?

C++

server.py

from ctypes import * 

PIPE_ACCESS_DUPLEX = 0x3 
PIPE_TYPE_MESSAGE = 0x4 
PIPE_READMODE_MESSAGE = 0x2 
PIPE_WAIT = 0 
PIPE_UNLIMITED_INSTANCES = 255 
BUFSIZE = 4096 
NMPWAIT_USE_DEFAULT_WAIT = 0 
INVALID_HANDLE_VALUE = -1 
ERROR_PIPE_CONNECTED = 535 

MESSAGE = "Default answer from server\0" 
szPipename = "\\\\.\\pipe\\mynamedpipe" 


def ReadWrite_ClientPipe_Thread(hPipe): 
    chBuf = create_string_buffer(BUFSIZE) 
    cbRead = c_ulong(0) 
    while 1: 
     fSuccess = windll.kernel32.ReadFile(hPipe, chBuf, BUFSIZE, 
byref(cbRead), None) 
     if ((fSuccess ==1) or (cbRead.value != 0)): 
      print chBuf.value 
      cbWritten = c_ulong(0) 
      fSuccess = windll.kernel32.WriteFile(hPipe,c_char_pc_char_p(MESSAGE),len(MESSAGE),byref(cbWritten),None) 
     else: 
      break 
     if ((not fSuccess) or (len(MESSAGE) != cbWritten.value)): 
      print "Could not reply to the client's request from the pipe" 
      break 
     else: 
      print "Number of bytes written:", cbWritten.value 

    windll.kernel32.FlushFileBuffers(hPipe) 
    windll.kernel32.DisconnectNamedPipe(hPipe) 
    windll.kernel32.CloseHandle(hPipe) 
    return 0 

def main(): 
    THREADFUNC = CFUNCTYPE(c_int, c_int) 
    thread_func = THREADFUNC(ReadWrite_ClientPipe_Thread) 
    while 1: 
     hPipe = windll.kernel32.CreateNamedPipeA(szPipename,PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, NMPWAIT_USE_DEFAULT_WAIT,None) 
     if (hPipe == INVALID_HANDLE_VALUE): 
      print "Error in creating Named Pipe" 
      return 0 

     fConnected = windll.kernel32.ConnectNamedPipe(hPipe, None) 
     if ((fConnected == 0) and (windll.kernel32.GetLastError() == ERROR_PIPE_CONNECTED)): 
      fConnected = 1 
     if (fConnected == 1): 
      dwThreadId = c_ulong(0) 
      hThread = windll.kernel32.CreateThread(None, 0, thread_func, hPipe, 0, byref(dwThreadId)) 
      if (hThread == -1): 
       print "Create Thread failed" 
       return 0 
      else: 
       windll.kernel32.CloseHandle(hThread) 
     else: 
      print "Could not connect to the Named Pipe" 
      windll.kernel32.CloseHandle(hPipe) 
    return 0 


if __name__ == "__main__": 
    main() 

Client.cpp

#include "stdafx.h" 
#include <windows.h> 
#include <stdio.h> 
#include <conio.h> 
#include <tchar.h> 

#define BUFSIZE 512 

int _tmain(int argc, TCHAR *argv[]) 
{ 
    HANDLE hPipe; 
    LPTSTR lpvMessage=TEXT("Default message from client."); 
    TCHAR chBuf[BUFSIZE]; 
    BOOL fSuccess = FALSE; 
    DWORD cbRead, cbToWrite, cbWritten, dwMode; 
    LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 

    if(argc > 1) 
     lpvMessage = argv[1]; 

// Try to open a named pipe; wait for it, if necessary. 

    while (1) 
    { 
     hPipe = CreateFile( 
     lpszPipename, // pipe name 
     GENERIC_READ | // read and write access 
     GENERIC_WRITE, 
     0,    // no sharing 
     NULL,   // default security attributes 
     OPEN_EXISTING, // opens existing pipe 
     0,    // default attributes 
     NULL);   // no template file 

    // Break if the pipe handle is valid. 

     if (hPipe != INVALID_HANDLE_VALUE) 
     break; 

     // Exit if an error other than ERROR_PIPE_BUSY occurs. 

     if (GetLastError() != ERROR_PIPE_BUSY) 
     { 
     _tprintf(TEXT("Could not open pipe. GLE=%d\n"), GetLastError()); 
     return -1; 
     } 

     // All pipe instances are busy, so wait for 20 seconds. 

     if (! WaitNamedPipe(lpszPipename, 20000)) 
     { 
     printf("Could not open pipe: 20 second wait timed out."); 
     return -1; 
     } 
    } 

// The pipe connected; change to message-read mode. 

    dwMode = PIPE_READMODE_MESSAGE; 
    fSuccess = SetNamedPipeHandleState( 
     hPipe, // pipe handle 
     &dwMode, // new pipe mode 
     NULL,  // don't set maximum bytes 
     NULL); // don't set maximum time 
    if (! fSuccess) 
    { 
     _tprintf(TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError()); 
     return -1; 
    } 

// Send a message to the pipe server. 

    cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR); 
    _tprintf(TEXT("Sending %d byte message: \"%s\"\n"), cbToWrite, lpvMessage); 

    fSuccess = WriteFile( 
     hPipe,     // pipe handle 
     lpvMessage,    // message 
     cbToWrite,    // message length 
     &cbWritten,    // bytes written 
     NULL);     // not overlapped 

    if (! fSuccess) 
    { 
     _tprintf(TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError()); 
     return -1; 
    } 

    printf("\nMessage sent to server, receiving reply as follows:\n"); 

    do 
    { 
    // Read from the pipe. 

     fSuccess = ReadFile( 
     hPipe, // pipe handle 
     chBuf, // buffer to receive reply 
     BUFSIZE*sizeof(TCHAR), // size of buffer 
     &cbRead, // number of bytes read 
     NULL); // not overlapped 

     if (! fSuccess && GetLastError() != ERROR_MORE_DATA) 
     break; 

     _tprintf(TEXT("\"%s\"\n"), chBuf); 
    } while (! fSuccess); // repeat loop if ERROR_MORE_DATA 

    if (! fSuccess) 
    { 
     _tprintf(TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError()); 
     return -1; 
    } 



    CloseHandle(hPipe); 

    return 0; 
} 

答えて

-1

たぶん、サーバはそのすべてのデータまで、ループ内のパイプからの読み取り試してみてくださいあなたが到達することを期待して、到達した(クライアントとのあなたのプロトコルに従って、例えば、 minatorが読まれました)。

+0

これは、2つの異なる言語を使用している場合にのみ発生します。しかし、PythonとC++の両方で同じ言語がうまく動作しています。 – Varanka

+0

@Varanka多分、読み込みのバッファリングが違うかもしれません。私は、予想されるすべてのデータが読み込まれるまで(またはEOFに達したときにパイプが閉じられるまで)、読んだ方が正しいと思います。 – selalerer

3

は、サーバーが受信したバッファのた.rawを印刷した場合、あなたはそれが実際にメッセージ全体を取得しています見ることができます:

> print repr(chBuf.raw) 

'D\x00e\x00f\x00a\x00u\x00l\x00t\x00 \x00m\x00e\x00s\x00s\x00a\x00g\x00e\x00 \x00f\x00r\x00o\x00m\x00\x00c\x00l\x00i\x00e\x00n\x00t\x00.\x00\x00\x00\x00\x00 ... \x00\x00' 

問題が間に散在NULL値(\ X00)があるということです正当な文字で、chBuf.valueを印刷しようとしているときはヌルターミネータのように見えます。なぜすべてのnulls?これは、あなたのC++クライアントが(LPTSTRを使用して)wchar_t *メッセージを送信しているが、Pythonサーバーがchar *文字列を要求しているためです。

変更この行:これまで

chBuf = create_string_buffer(BUFSIZE) 

chBuf = create_unicode_buffer(BUFSIZE) 

これは、問題を修正する必要があります。

あなたはここにコピー&ペーストのエラーを持っているようにああ、また、見えます:

fSuccess = windll.kernel32.WriteFile(hPipe,c_char_pc_char_p(MESSAGE),len(MESSAGE),byref(cbWritten),None) 

それは次のようになります。

fSuccess = windll.kernel32.WriteFile(hPipe, c_char_p(MESSAGE),len(MESSAGE),byref(cbWritten),None) 

私は私まで、Pythonコードで名前のエラーを得ましたそれを変更しました。

+1

より具体的には、Windows TEXT()マクロは、UNICODEが#defineされているかどうかに応じてANSIまたはUTF-16文字列を生成します。 http://msdn.microsoft.com/en-us/library/windows/desktop/dd374074(v=vs.85).aspx –

+0

ニース!だから、C++側とPython側のどちらかでコードを修正する方法があります:) – NattyBumppo

関連する問題