5 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);
   }
}

信息补充,监听者流程:

← 限制状态机 为节点制作Tcp Table →
 
comments powered by Disqus