2013-10-15 44 views
0

進出口不能不說是一個初來乍到C(其實所有的編譯語言),下面你會看到我可怕的代碼,我嘗試接收命令後,我希望執行它(未實現然而)。_popen崩盤的Windows - C]

我grapped從微軟的示例代碼的_popen功能,修改了它(非常輕微),但由於某種原因,它已收到命令後,這個崩潰我的程序。如果我將這塊代碼移動到命令接收器部分上面,它就可以工作。我是否覆蓋另一個內存地址或什麼?

如果您需要服務器(用python編寫),請讓我知道。希望你能幫助需要的noob。

#include <winsock2.h> 
#include <stdio.h> 
#include <windows.h> 

int sendall(int sock, char *message, unsigned int size); 
int connect(char address[], short port); 
char* recvall(int sock, unsigned int *msgsize); 


int main(){ 
    char address[] = "127.0.0.1"; 
    short port = 1234; 
    int wait = 5000; 

    //Connect back 
    int sock = 1; 
    printf("Connecting...\n"); 
    sock = connect(address, port); 
    while(sock == 1){ 
     WSACleanup(); 
     Sleep(wait); 
     sock = connect(address, port); 
    } 

    printf("Succesfully conneted\n"); 

    char test[] = "ABCDEFGH"; 
    sendall(sock,test, 8); 

    unsigned int msgsize; 
    char *msg = recvall(sock,&msgsize); 


    printf("%s\n", msg); 
    printf("%d\n", msgsize); 


    //RUN COMMAND 

    char psBuffer[128]; 
    FILE *pPipe; 


    printf("There\n"); 

    if((pPipe = _popen("ipconfig", "rt")) == NULL) 
     exit(1); 

    printf("Out\n"); 

    while(fgets(psBuffer, 128, pPipe)){ 
     printf(psBuffer); 
    } 


    if (feof(pPipe)){ 
     printf("\nProcess returned %d\n", _pclose(pPipe)); 
    }else{ 
     printf("Error: Failed to read the pipe to the end.\n"); 
    } 

    //RUN COMMAND END 

    Sleep(10000); 
    return 0; 
} 

int sendall(int sock, char *message, unsigned int size){ 

    //Send size packet 
    char sizepacket[12]; 
    sprintf (sizepacket, "%012u",size); 
    send(sock, sizepacket, 12, 0); 

    //Send data 
    unsigned int left = size; 
    unsigned int offset = 0; 
    while(left>0){ 
     if(left<1024){ 
      send(sock, (message+offset), left, 0); 
      left = 0; 
     }else{ 
      send(sock, (message+offset), 1024, 0); 
      offset = offset + 1024; 
      left = left - 1024; 
     } 
    } 
    return 0; 
} 

char* recvall(int sock, unsigned int *size){ 
    char *message; 

    //Get size packet 
    char sizebuff[24]; 
    memset (&sizebuff,0,24); 
    recv(sock, sizebuff, 12, 0); 
    *size = atoi(sizebuff); 

    //Alloc space for message 
    message = (char*) malloc(*size + 1); 
    memset(message,0,1024); 

    //Get data 
    unsigned int left = *size; 
    unsigned int offset = 0; 
    while(left>0){ 
     if(left<1024){ 
      recv(sock, (message+offset), left, 0); 
      left = 0; 
     }else{ 
      recv(sock, (message+offset), 1024, 0); 
      offset = offset + 1024; 
      left = left - 1024; 
     } 
    } 
    return message; 
} 



int connect(char address[], short port){ 
    int returnvalue; 

    WSADATA wsaData; 

    returnvalue = WSAStartup(MAKEWORD(2,2), &wsaData); 
    if(returnvalue != 0){ 
     return 1; 
    } 

    int sock; 
    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if(sock == 0){ 
     return 1; 
    } 


    //Create struct 
    struct sockaddr_in clientService; 
    clientService.sin_family = AF_INET; 
    clientService.sin_addr.s_addr = inet_addr(address); 
    clientService.sin_port = htons(port); 


    returnvalue = connect(sock, (SOCKADDR*) &clientService, sizeof(clientService)); 
    if (returnvalue != 0){ 
     closesocket(sock); 
     WSACleanup(); 
     return 1; 
    } 

    return sock; 
} 

回答

1

您的popen似乎不依賴於您的套接字通信。

請描述你的服務器發送(hexdump都可以?)消息

請看看你的recvall()函數。您從套接字讀取12個字節,將其轉換爲int,並將malloc轉換爲多個字節,然後將其存儲爲*大小,然後memset設置大小爲1024的消息緩衝區(只是malloc'ed)。然後,您會收到消息緩衝區,但沒有警衛來確保你不會超出消息的結尾[* size]。

int main(){ 
    //... 
    unsigned int msgsize; 
    char *msg = recvall(sock,&msgsize); 
    printf("%d\n", msgsize); 
    printf("%s\n", msg); 
    return 0; 
} 

char* recvall(int sock, unsigned int *size){ 
    char *message; 
    //Get size packet 
    char sizebuff[24]; 
    memset (&sizebuff,0,24); 
    recv(sock, sizebuff, 12, 0); 
    *size = atoi(sizebuff); 
    printf("size: %d\n",*size);fflush(stdout); 
    //Alloc space for message 
    message = (char*) malloc(*size + 1); 
    memset(message,0,1024); //why 1024? why not *size? 
    //Get data 
    unsigned int left = *size; 
    unsigned int offset = 0; 
    while(left>0){ 
     if(left<1024){ 
      recv(sock, (message+offset), left, 0); 
      left = 0; 
     }else{ 
      recv(sock, (message+offset), 1024, 0); //why 1024? 
      offset = offset + 1024; //again, why 1024?, this is > 1024 
      left = left - 1024; 
     } 
    } 
    return message; 
} 
+0

我覺得自己太愚蠢了......吮吸某物是我猜的第一步。你的第一個1024是正確的 - 最後一個是因爲我收到了1024字節塊的消息,但現在編譯完美。非常感謝! – Cshark

+0

你正在學習,並在不斷髮展。樂意效勞。 – ChuckCottrill

0

你的榜樣,因爲你有connect()函數的兩個版本將不是我的系統上編譯 - 當地connect()功能本身在這一行內本地通話和系統版本,從名爲:

returnvalue = connect(sock, (SOCKADDR*) &clientService, sizeof(clientService)); 

嘗試將您的本地版本更改爲不同的名稱,例如xconnect()。我很驚訝你的編譯器允許這樣做。

+0

雖然它被標記爲C,但OP可能將程序編譯爲C++,在這種情況下這不會成爲問題(兩個連接函數具有不同的簽名)。 –

+0

@馬克威爾金斯 - 謝謝。你可能是對的。我考慮過這個問題,但是我沒有在代碼中看到任何「明顯是C++」的語法,加上OP聲稱使用C(雖然是一個被認可的新手)。 – willus