我编写了这个程序,它监听给定的端口,然后,一旦收到连接,就输出一行文本并断开连接。它运行了几天,处理了数千个查询,但随后(不可避免地)崩溃,我必须重新启动它。想知道是否有人认为它有任何问题,或者(或者)如果有人能提出一种方法使其更加健壮。
int main(int argc, char *argv[])
{
srand(time(0));
int sockfd, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
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)
{
unsigned char write_val;
unsigned char y[BYTES];
int i, j;
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
fill_buffer(y); // fills buffer y with a 128-bit string; not included here
for (i=BYTES-1; i >= 0; i--)
{
const void* ZERO = (void *)"0";
const void* ONE = (void *)"1";
for (j=7; j >= 0; j--)
write(newsockfd, (y[i] >> j) & 1 ? ONE : ZERO, 1);
}
write(newsockfd, "\n", 1);
close(newsockfd);
}
close(sockfd);
return 0;
}
答案 0 :(得分:2)
任何人都认为它有什么问题
虽然这段代码可以提高效率(例如通过在一次传递中写入所有字节),但那里没有明显的缺陷。
这使得代码中未发布的部分成为问题的理想选择:
fill_buffer(y); // fills buffer y with a 128-bit string; not included here
如果您读取的字节数超过y[]
的大小,则会崩溃。
或(或者)如果有人可以建议一种方法使其更健壮
尝试扩大此y[]
缓冲区的大小(加倍可以不受伤害)。
并确保fill_buffer()
不能读取超过BYTES
个字符。
如有疑问,请发布此遗失的代码。
您还可以使用调试符号编译代码,并在信号处理程序的文件中转储回溯(带符号)。这样,如果您的程序崩溃,您就会知道where
和why
。
答案 1 :(得分:1)
代码看起来很好用一些评论。 一个有点重要的评论: portno应声明为unsigned short。对于类似英特尔(小端)的处理器,它可以正常工作,但它不能移植到具有不同字节序的处理器。
无论如何,这不是你的进程崩溃的原因。
显然,在'while'内执行时会发生崩溃,并且通过查看代码,如果崩溃导致缓冲区溢出,唯一的可能就是fill_buffer。
如果您显示BYTES和fill_buffer的定义,那么将更容易为您提供帮助。
现在,如果它不是缓冲区溢出,如果客户端在服务器写入套接字之前关闭了连接,则有可能在写入时中止。在这种情况下,进程将收到SIGPIPE信号,如果代码不处理该信号,它将中止。
你也可以忽略SIGPIPE:
signal(SIGPIPE, SIG_IGN);
其他可能性是,如果你正在使用write_val做一些奇怪的事情而你没有显示该代码。
我希望这会有所帮助。