2012-01-30 2 views
0

커스텀 VNC 서버 - 클라이언트를 쓰고 있습니다. 그러나 매번 159 개의 명령을 실행하면 서버가 충돌합니다. 나는 그것이 왜 충돌 하는지를 알 수는 없지만 어딘가에서 일종의 메모리 넘치는 것처럼 보인다. 소켓이나 std-i/o가 채워질 수 있습니까? 아니면 내 X 컨트롤로 뭔가 더 가능성이 있습니까?C 소켓 오버 플로우 메모리

소스 코드 :

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <sys/wait.h> 
#include <sys/select.h> 
#include <X11/Xlib.h> 
#include <X11/Xutil.h> 
#include <X11/extensions/XTest.h> 



void dostuff(int); 


void error(const char *msg) 
     { 
     perror(msg); 
     exit(1); 
     } 

int main(int argc, char *argv[]) 
     { 
     int sockfd, newsockfd, portno, pid; 
     socklen_t clilen; 
     struct sockaddr_in serv_addr, cli_addr; 

     if (argc < 2) 
       { 
       fprintf(stderr,"ERROR, no port provided\n"); 
       exit(1); 
       } 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    portno = atoi(argv[1]); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 
    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
       error("ERROR on binding"); 
    listen(sockfd,5); 
    clilen = sizeof(cli_addr); 


     while (1) 
       { 
       newsockfd = accept(sockfd, 
       (struct sockaddr *) &cli_addr, &clilen); 
       if (newsockfd < 0) 
       error("ERROR on accept"); 
       pid = fork(); 
       if (pid < 0) 
         error("ERROR on fork"); 
       if (pid == 0) 
         { 
         close(sockfd); 
         dostuff(newsockfd); 
         exit(0); 
         } 
       else close(newsockfd); 
       signal(SIGCHLD,SIG_IGN); 
       } 

     /* end of while */ 
     close(sockfd); 
     return 0; /* we never get here */ 
} 

/******** DOSTUFF() ********************* 
There is a separate instance of this function 
for each connection. It handles all communication 
once a connnection has been established. 
*****************************************/ 
void dostuff (int sock) 
{ 
while(1) 
     { 
     fflush(stdout); 

     int n; 
     char buffer[64]; 

     bzero(buffer,64); 
     printf("START:\n"); 
     n = read(sock,buffer,63); 
     printf("buffer[1]: %d \n", buffer[1]); 
     if (n < 0) error("ERROR reading from socket"); 


     Display *thedisplay; 
     Window thewindow; 
     int screen; 
     screen=buffer[0]-48; //first element is always the screen number 
     printf("screen = %d \n", screen); 

     thedisplay=XOpenDisplay(NULL); 
     thewindow=XRootWindow(thedisplay,screen); 
     int screenwidth = DisplayWidth(thedisplay, screen); 
     int screenheight = DisplayHeight(thedisplay, screen); 
     printf("width: %d, height %d \n", screenwidth, screenheight); 

     printf("buff[1] = %d \n", buffer[1]); 

     //switch on second char 
     switch(buffer[1]) 
     { 
     case 109: // second element == 'm' we treat it like a mousemove 

       printf("mousemovement\n"); 
       int xcoord = 100*(buffer[3]-48)+10*(buffer[4]-48)+1*(buffer[5]-48); 
       int ycoord = 100*(buffer[7]-48)+10*(buffer[8]-48)+1*(buffer[9]-48); 
       if (buffer[2]==49) xcoord = xcoord*(-1); 
       if (buffer[6]==49) ycoord = ycoord*(-1); 
       //printf("dx: %d, dy: %d \n", xcoord, ycoord); 
       Window windowreturned; 
       int xroot, yroot, xwin, ywin, mask_return; 
       XQueryPointer(thedisplay, thewindow, &windowreturned, &windowreturned, &xroot, &yroot, &xwin, &ywin, &mask_return); 
       //printf("xroot X: %d Y: %d \n", xroot, yroot); 
       //printf("xcoord+xroot %d %d \n", xcoord+xroot, ycoord+yroot); 
       //printf("screenwidth %d %d \n", screenwidth, screenheight); 
       if (xcoord+xroot > 0 && xcoord+xroot < screenwidth && ycoord+yroot>0 && ycoord+yroot<screenheight) 
        { 
        //printf("good to go\n"); 
        XWarpPointer(thedisplay,None,None,0,0,0,0,xcoord,ycoord); 
        XSync(thedisplay, False); 
        } 
       break; 
     case 107: //second element is a 'k' so we sendkey 
       SendKey (thedisplay, buffer[2]); 
       break; 
     case 98: // b us for mousebutton. 1 is leftclick, 2 is middle click, 3 is right click, 4 us up-scroll, 5 is downscroll 
       XTestGrabControl(thedisplay, True); 
//    XTestFakeButtonEvent(thedisplay, 1, True, 0); 
//    XTestFakeButtonEvent(thedisplay, 1, False, 0); 
       XTestFakeButtonEvent(thedisplay, buffer[2]-48, True, 0); 
       XTestFakeButtonEvent(thedisplay, buffer[2]-48, False, 0); 
       XSync (thedisplay, False); 
       XTestGrabControl (thedisplay, False); 
       break; 
     case 99: //second element is 'c', so we center on the screen 

       XWarpPointer(thedisplay,None,thewindow,0,0,0,0,screenwidth*.5,screenheight*.5); 
       XSync(thedisplay, False); 
       break; 

     default: 
       close(sock); 
       error("ERROR incorrect formattttttt\n"); 
       break; 
     } 

    printf("got this far\n"); 
    n = write(sock,"spanks\n",6); 
    if (n < 0) error("ERROR writing to socket\n"); 

} 
} 
+1

서버가 다운되었다고 할 때 정확히 무엇을 의미합니까? 오류 메시지가 있습니까? 멈 춥니 다? 그 과정이 멈출까요? 스택 덤프가 있습니까? –

+1

만약 read()가 단지 3 바이트를 반환한다면? 또는 각각 20 바이트 인 2 개의 명령을 보내고 read() 호출이 양쪽 모두를 읽고 40 바이트를 반환하면 어떻게 될까요? 즉, 프로토콜 및 코드에 대한 메시지 구조 및 메시지 프레임을 정의하지 않은 것 같습니다. – nos

+0

클라이언트 쪽에서는 SIGPIPE 오류 – cyrusv

답변

0

어떻게 dostuff의 끝에서 소켓을 닫으려고에 대한()? 서버가 너무 많은 연결을 열었을 수 있습니다.

+0

dostuff()는 한 번만 호출되고 while (1) 루프에서는 열린 상태로 유지되므로 서버에 열린 연결이 하나 뿐이라고 확신합니다. – cyrusv

1

읽기를 호출한다고해서 63 바이트가 모두 수신되거나 63 바이트를 수신한다고 보장 할 수는 없습니다. 수신 할 데이터의 양을 어떻게 든 결정할 것을 제안합니다. 길이 먼저) 그리고 모든 데이터를 가질 때까지 recv 함수를 루프에 넣으십시오 .. 클라이언트로부터의 send 함수도 검사해야합니다.

+0

예. 액세스 할 수 있습니다. 코드는 정상적으로 작동하지만 약 159 회 반복됩니다. – cyrusv

+0

읽기가 재미 있습니다. 클라이언트와 서버 코드에 대한 읽기 및 쓰기 크기가 일치한다고 생각합니다. 일치하지 않으면 많은 반복 작업 후에 충돌이 발생할 수 있습니까? – cyrusv

+0

'buffer [0] - 48'은 ASCII 숫자를 이진 형식으로 변환합니다 (즉, ''9 => 9'). – dreamlax

0

솔루션 : XOpenDisplay가 닫히지 않고 무한 루프 내에있는 것이 오류입니다. 나는 단순히 dostuff()의 무한 루프 앞에서 XOpenDisplay 명령을 움직였다.

사실 소켓 오류가 아닙니다.