3 months ago
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/socket.h" //套接字函数库
#include "arpa/inet.h" //网络协议套接字函数库
//读文件的函数
char *read_file(char *path, int *length) {
FILE *file;
char *contents;
file = fopen(path, "r+");
fseek(file, 0, SEEK_END);
*length = ftell(file);
fseek(file, 0, SEEK_SET);
contents = malloc(*length);
fread(contents, 1, *length, file);
fclose(file);
return contents;
}
//建立监听者套接字
int establish(int port)
{
int listener;
struct sockaddr_in address;
address.sin_family = 2;
address.sin_port = htons(port);
address.sin_addr.s_addr = inet_addr("0.0.0.0");
if ((listener = socket(2, 1, 0)) == -1)
exit(116);
if (bind(listener, (struct sockaddr *) &address, sizeof (address)) == -1)
exit(148);
if (listen(listener, 1024) == -1)
exit(75);
return listener;
}
//主代码
int main(int count, char **arguments) {
char *content;
int acceptor, listener, size;
//参数不能少于三个,否则退出
if (count < 3)
exit(21);
//读取第二个参数,即文件内容
content = read_file(arguments[1], &size);
//第三个参数为监听端口,开始监听
listener = establish(atoi(arguments[2]));
while (1) {
struct sockaddr_in _7231;
int _8352 = 16;
char *_9710;
//accpet是一个系统呼叫,每一次新的连接被建立都会运行accept,有三个参数,第一个为监听者的端口,第二个和第三个为option(选填),在这里为了接受连接者的IP地址,第二个参数放入了一个指向连接者IP地址的指针,第三个参数就是这个IP地址的长度
acceptor = accept(listener, (struct sockaddr *) &_7231, &_8352);
_9710 = (char *) &(_7231.sin_addr.s_addr);//将IP地址转换成四个字节的通用IP地址的格式
printf("%hhu.%hhu.%hhu.%hhu%c", _9710[0], _9710[1], _9710[2], _9710[3], 10);//打印IP地址
printf("a connection has occurred (%d)%c", time(0), 10);
//这是HTTP信息包头部,设置好了状态码(200),然后连接一次性还是连续性(这里是一次性),然后是内容长短和内容类型,然后将content(这个文件)复制到最后面
char *_2783 = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Length: %d$
char *_2279 = malloc(10000);
sprintf(_2279, _2783, size);
char *_8931 = malloc(size + strlen(_2279));
memcpy(_8931, _2279, strlen(_2279));
memcpy(_8931 + strlen(_2279), content, size);
//发送将整个信息发送给连接者,只需要在某个浏览器输入监听者的IP地址和监听端口,就可以看到这个content文件内容
send(acceptor, _8931, strlen(_2279) + size, 0);
//因为是循环,所以要释放内存
free(_8931);
}
}
信息补充,监听者流程: