C套接字溢出内存

C套接字溢出内存,c,sockets,x11,vnc,xserver,C,Sockets,X11,Vnc,Xserver,我正在编写一个定制的VNC服务器客户端。但是,每次执行159个命令后,服务器就会崩溃。我不明白它为什么会崩溃,但似乎是某个地方的内存溢出。插座或std-i/o是否可能充满?还是更像是我的X控件 源代码: #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys

我正在编写一个定制的VNC服务器客户端。但是,每次执行159个命令后,服务器就会崩溃。我不明白它为什么会崩溃,但似乎是某个地方的内存溢出。插座或std-i/o是否可能充满?还是更像是我的X控件

源代码:

#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");

 }
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
空隙度凝灰岩(int);
无效错误(常量字符*消息)
{
佩罗尔(味精);
出口(1);
}
int main(int argc,char*argv[])
{
int sockfd、newsockfd、端口号、pid;
socklen_t clilen;
服务地址中的结构sockaddr\u,cli\u addr;
如果(argc<2)
{
fprintf(stderr,“错误,未提供端口\n”);
出口(1);
}
sockfd=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
错误(“打开套接字时出错”);
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(端口号);
if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
错误(“绑定错误”);
听(sockfd,5);
clilen=sizeof(cli_addr);
而(1)
{
newsockfd=接受(sockfd,
(结构sockaddr*)和cli_addr和clilen);
if(newsockfd<0)
错误(“接受错误”);
pid=fork();
if(pid<0)
错误(“叉子上的错误”);
如果(pid==0)
{
关闭(sockfd);
dostuff(newsockfd);
出口(0);
}
否则关闭(newsockfd);
信号(信号灯、信号灯);
}
/*结束*/
关闭(sockfd);
返回0;/*我们永远无法到达这里*/
}
/********多斯塔夫()*********************
此函数有一个单独的实例
对于每个连接。它处理所有的通信
一旦建立了连接。
*****************************************/
空隙度凝灰岩(内部短袜)
{
而(1)
{
fflush(stdout);
int n;
字符缓冲区[64];
bzero(缓冲器,64);
printf(“开始:\n”);
n=读取(sock,buffer,63);
printf(“缓冲区[1]:%d\n”,缓冲区[1]);
如果(n<0)错误(“从套接字读取错误”);
显示*显示器;
窗户,窗户;
int屏幕;
screen=buffer[0]-48;//第一个元素始终是屏幕编号
printf(“屏幕=%d\n”,屏幕);
显示=xOpen显示(空);
窗口=XRootWindow(显示器,屏幕);
int screenwidth=显示宽度(显示器,屏幕);
int screenheight=显示高度(显示器,屏幕);
printf(“宽度:%d,高度%d\n”,屏幕宽度,屏幕高度);
printf(“buff[1]=%d\n”,缓冲区[1]);
//打开第二个字符
开关(缓冲区[1])
{
案例109://第二个元素=='m'我们将其视为鼠标移动
printf(“鼠标移动”);
int xcoord=100*(缓冲区[3]-48)+10*(缓冲区[4]-48)+1*(缓冲区[5]-48);
int ycoord=100*(缓冲区[7]-48)+10*(缓冲区[8]-48)+1*(缓冲区[9]-48);
如果(缓冲器[2]==49)xcoord=xcoord*(-1);
如果(缓冲器[6]==49)ycoord=ycoord*(-1);
//printf(“dx:%d,dy:%d\n”,xcoord,ycoord);
窗口返回;
int xroot、yroot、xwin、ywin、mask_return;
XQueryPointer(显示、窗口、窗口返回、窗口返回、xroot、yroot、xwin、ywin和掩码返回);
//printf(“xroot X:%d Y:%d\n”,xroot,yroot);
//printf(“xcoord+xroot%d%d\n”,xcoord+xroot,ycoord+yroot);
//printf(“屏幕宽度%d%d\n”,屏幕宽度,屏幕高度);

如果(xcoord+xroot>0&&xcoord+xroot0&&ycoord+yroot尝试关闭dostuff()末尾的套接字如何?
服务器可能获得了太多打开的连接。

简单地调用read并不能保证您将收到所有63字节或您希望收到的63字节。我建议您以某种方式确定需要接收的数据量(首先发送数据长度)然后将recv函数放入一个循环中,直到获得所有数据。.还应检查发送函数(来自客户端)。

解决方案:错误在于XOpenDisplay位于一个无限循环中而没有关闭。我只是将XOpenDisplay命令移到DOSTUF()中无限循环之前


事实上,这不是套接字错误。

当你说服务器崩溃时,你的确切意思是什么?有错误消息吗?它挂起了吗?进程刚刚停止了吗?你得到了堆栈转储吗?如果read()只返回3个字节呢?或者如果你发送了2个命令,每个命令都是20个字节,然后你的read()呢调用read并返回40字节?即,在客户端,您似乎没有为协议和代码定义消息结构和消息框架。(碰巧是一个iOS设备)。客户端上有SIGPIPE?这意味着服务器上的套接字已关闭。您在服务器上看到了哪些消息/错误?一般来说,您必须忽略SIGPIPE信号或捕获它们。在程序开始时执行以下操作:信号(SIGPIPE,SIG_IGN);这将确保对封闭套接字的任何写入操作都将返回-1,同时防止应用程序转储核心(或崩溃)。dostuff()只调用一次,并在while(1)循环中保持打开状态,因此我非常确定服务器只有一个打开的连接。是的,我确定我可以访问该连接。代码运行良好,但仅用于大约159次迭代。r