2012-01-30 5 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 байта? Или что, если вы отправляете 2 команды, каждая из которых составляет 20 байт, а ваш вызов read() читает их оба и возвращает 40 байт? то есть, похоже, вы не определили структуру сообщений и структуру сообщений для своего протокола и кода. – nos

+0

это ошибка SIGPIPE – cyrusv

ответ

0

Как о попытке закрыть сокет в конце DoStuff()? На сервере может быть слишком много открытых подключений.

+0

dostuff() вызывается только один раз и остается открытым в течение (1) цикла, поэтому я уверен, что на сервере есть только одно открытое соединение. – cyrusv

1

Просто вызов чтения не гарантирует, что вы получите все 63 байта или получите 63 байта, на которые вы надеялись .. Я бы предложил вам как-то определить, сколько данных вам нужно получить (отправить данные сначала), а затем поместить функцию recv в цикл до тех пор, пока у вас не будет всех данных. Также необходимо проверить функцию отправки (от клиента).

+0

Да, я уверен, что могу получить доступ к этому. Код работает нормально, но только около 159 итераций. – cyrusv

+0

Чтение интересно. Тем не менее, я считаю, что мой код для чтения и записи для кода клиента и сервера. Если они не совпадают, может ли это привести к сбою после многих итераций? – cyrusv

+0

'buffer [0] - 48' превращает цифру ASCII в двоичную форму (т. Е.' '9' => 9'). – dreamlax

0

Решение: ошибка заключалась в том, что XOpenDisplay находился внутри бесконечного цикла, не будучи закрытым. Я просто переместил команду XOpenDisplay перед бесконечным циклом в dostuff().

Это была не ошибка сокета.

 Смежные вопросы

  • Нет связанных вопросов^_^