所以我正在研究一个读取文件并将其内容输出到套接字的方法。
但是,我的浏览器显示了以下内容,而不是我的简单index.html文件:
#öÇdÿ GÊdÿ(˜ÊdÿÎ+Yÿ@0Çdÿ ŸÊdÿÐÎ+YÿÍ×ÇdÿHÌÊdÿèÌÊdÿ@Î+YÿlñÇdÿ ŸÊdÿ8öŒÿ¶¢ð‘ÿÎ+YÿòXÈdÿ GÊdÿ ŸÊdÿؾÊdÿâ@”ÐÎ+YÿŠÈdÿ Ð+Yÿ ŸÊdÿ ²Êdÿâ@”Ï+YÿŠÈdÿ Ð+YؾÊdÿ°0ÊdÿؾÊdÿ°0Êdÿ°0Êdÿ ŸÊdÿ`Ï+Yÿ¡Èdÿ°0Êdÿ ŸÊdÿ°0Êdÿâ@” Ð+Yÿ°Ï+YÿcbÈdÿ Ð+Yÿ¼À‡¨Qµpÿ8A”ë@”p0” ŸÊdÿPÐ+Yÿ¨ ®ÿ «ª2Ð+Yÿ©$®ÿ„Ð+Yÿ€Ð+Yÿ|Ð+Yÿ†Æuÿ€¸†Æuÿ€wÈ` †ÆuÿèƒÆuÿ yÆuÿ†Æuÿ Ð+Yÿó(®ÿU«""öèƒÆu` ƒƒèƒÆuÿ/”ÐÐ+YÿÕ;$ŒÿèƒÆuÿ/”ôÆuÿÐÑ+Yÿ$Œÿ †ÆuÿU«""ö@Ð+Yÿin:/bin:/usr/sbin:/sbin:/usr/locusr/local/bin:/usr/local/git/bin0àÑ+YÿàÐ+Yÿusername
代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PORT 8080
#define PROTOCOL 0
#define BACKLOG 10
#define BUFLEN 1500
void serve_file(int sock, char* filename)
{
char buffer[1024];
FILE *file;
// Open file for reading
file = fopen(filename, "rb");
if (!file) {
printf("Error: can't open file for reading");
return;
}
if ((fgets(buffer, sizeof buffer, file)) != NULL) {
int sent = send(sock, &buffer, sizeof buffer, 0);
if (sent == -1) {
printf("Error: send to socket failed\n");
printf("Error code: %s\n", strerror(errno));
}
} else {
printf("Error: could not read file contents");
return;
}
// Bye
fclose(file);
}
int main()
{
int fd;
int connfd;
// For bind()
struct sockaddr_in addr;
// For accept()
struct sockaddr_in cliaddr;
socklen_t cliaddrlen = sizeof(cliaddr);
// For reading and writing
ssize_t i;
ssize_t rcount;
char buffer[BUFLEN];
// Open a socket
fd = socket(AF_INET, SOCK_STREAM, PROTOCOL);
if (fd == -1) {
printf("Error: unable to open a socket\n");
printf("Error code: %s\n", strerror(errno));
exit(1);
}
// Create an address
//memset(&addr, 0, sizeof addr);
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
int yes = 1;
if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 )
{
perror("setsockopt");
}
if ((bind(fd, (struct sockaddr *)&addr, sizeof(addr))) == -1) {
printf("Error: unable to bind\n");
printf("Error code: %s\n", strerror(errno));
exit(1);
}
// Listen for connections
if ((listen(fd, BACKLOG)) == -1) {
printf("Error: unable to listen for connections\n");
printf("Error code: %s\n", strerror(errno));
exit(1);
}
// Accept connections
connfd = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen);
if (connfd == -1) {
printf("Error: unable to accept connections\n");
printf("Error code: %s\n", strerror(errno));
exit(1);
}
// Read data
rcount = read(connfd, buffer, BUFLEN);
if (rcount == -1) {
printf("Error: unable to accept connections\n");
printf("Error code: %s\n", strerror(errno));
exit(1);
}
for (i = 0; i < rcount; i++) {
printf("%c", buffer[i]);
}
//write(connfd, buffer, rcount);
serve_file(connfd, "index.html");
// Bye
close(connfd);
return 0;
}
答案 0 :(得分:3)
更改
int sent = send(sock, &buffer, sizeof buffer, 0);
是
int sent = send(sock, &buffer, strlen(buffer), 0);
仅发送fgets()
已阅读的内容。
此外,请注意,send()
并不需要发送尽可能多的字节。
要确保发送外包,请测试send()
的结果以查看实际发送的数量,然后循环send()
以发送其余内容。
来自man send
:
成功时,这些调用将返回发送的字节数。
同样send()
返回ssize_t
而不是int
。
另外^ 2至少是:
int main(void)
另外^ 3:如果fclose()
返回fgets()
,则代码会错过NULL
文件,当它达到EOF时,它肯定会做什么。
同样^最后:serve_file()
只读取(并发送)文件的第一行。
要解决此更改
if ((fgets(buffer, sizeof buffer, file)) != NULL) {
int sent = send(sock, &buffer, sizeof buffer, 0);
if (sent == -1) {
printf("Error: send to socket failed\n");
printf("Error code: %s\n", strerror(errno));
}
} else {
printf("Error: could not read file contents");
return;
}
看起来像这样
while ((fgets(buffer, sizeof buffer, file)) != NULL) {
...
}
if (ferror(file)) {
printf("Error reading file contents.");
}