我正在用c代码实现一个简单的http服务器。 我通过firefox浏览器作为客户端连接到服务器,并写:
http://localhost:<port number>/<path to file>
现在,我尝试了一个简单的文本文件,它的工作原理。但是,当我尝试使用图像时,它不起作用。 重要的是要提到几天前它确实有效,但是由于我从TA获得的一些注释,我改变了我的代码,现在它不起作用......
我添加了一些辅助打印件并看到一些数据已发送,但是在某些时候它会卡住并且不再发送。 我的猜测是,不知何故发送缓冲区被填满了,但我确保在发送结束后它是空的...你能尝试找出问题所在吗?
#define BUF_SIZE 2048
int sendToClient(int clientFd, char *buf)
{
int bytesSent;
int totalSent = 0;
size_t notSent = strlen(buf);
while (notSent > 0)
{
if ((bytesSent = send(clientFd, buf + totalSent, notSent, 0)) < 0)
{
printf("send syscall failed: %s\n", strerror(errno));
return -1;
}
notSent -= bytesSent;
totalSent += bytesSent;
}
return totalSent;
}
void handleFile(int sockFd, char *path, struct stat *statBuf)
{
//the stat structure pointer is delivered as a parameter,
//it already contains info about the file we want to send
//sockFd is the client's socket file descriptor.
//path is the path to the file...
size_t totalBytesToSend = (size_t) statBuf->st_size;
int fd = open(path, O_RDONLY, 0777);
if (fd < 0)
{
printf("open syscall failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// sending some initial http stuff...
char buf[BUF_SIZE];
// zero buffer
memset(buf, 0, BUF_SIZE);
int bytesSent;
while (totalBytesToSend > 0)
{
if (read(fd, buf, BUF_SIZE) < 0)
{
printf("read syscall failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
//send buf to client
if ((bytesSent = sendToClient(sockFd, buf)) < 0)
{
exit(EXIT_FAILURE);
}
// data was sent - zero buf again
memset(buf, 0, BUF_SIZE);
totalBytesToSend -= bytesSent;
}
//close file & socket
close(fd);
close(sockFd);
}
谢谢!
答案 0 :(得分:2)
错误在于:size_t notSent = strlen(buf);
。您假设缓冲区中的第一个空标记从文件读取的数据的结尾。对于永远不应包含空字节的文本文件有意义,但对于像图像文件这样的二进制文件,它是错误的假设。因为它们可以包含空字节,所以不会将从文件读取的所有字节传输到客户端,最坏的情况是缓冲区的第一个字节是0!
您必须将实际从磁盘读取的字节数传递给sendToClient
函数并使用它。永远不要假设特定字节或序列永远不会出现在二进制文件中......