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