Exemplo n.º 1
0
int main(int argc,char **argv)
{
	//服务器socket号
	int server_sock;
	int client_sock;
	//端口号
	int port;
	int client_addr_len;
	struct sockaddr_in client_addr;
	pthread_t thread_id;
	if(argc!=2){
		perror("please run it like: ./tinyweb port");
		exit(EXIT_FAILURE);
	}
	
	//把字符串类型端口号转为整型
	port = atoi(argv[1]);
	
	//初始化服务器socket号
	server_sock=start_up(port);
	client_addr_len=sizeof(client_addr);
	
	//不断循环,不断接收客户端的链接请求
	while(1){
		//accept函数返回值,初始化客户socket号,以后获取客户端的内容和向客户端发送信息都
		//通过这个端口号
		client_sock = accept(server_sock,(struct sockaddr *)&client_addr,&client_addr_len);

		if(client_sock == -1){
			error_die("accept error\n");
		}
		
		//创建新的线程来为客户端服务,主要pthread_create这个函数的参数
		if(pthread_create(&thread_id,NULL,(void *)deal_request,(void *)&client_sock)!=0)
			error_die("pthread_create error\n");
	}
	
	close(server_sock);
	return 0;
}
Exemplo n.º 2
0
void check_header_gzip(int src_fd)
{
    union {
        unsigned char raw[8];
        struct {
            unsigned char method;
            unsigned char flags;
            unsigned int mtime;
            unsigned char xtra_flags;
            unsigned char os_flags;
        } formatted;
    } header;

    xread(src_fd, header.raw, 8);

    /* Check the compression method */
    if (header.formatted.method != 8)
/*        error_die("Unknown compression method %d", header.formatted.method);*/
        error_die("Unknown compression method");

    if (header.formatted.flags & 0x04)
    {
        /* bit 2 set: extra field present */
        unsigned char extra_short;

        extra_short = xread_char(src_fd) + (xread_char(src_fd) << 8);
        while (extra_short > 0)
        {
            /* Ignore extra field */
            xread_char(src_fd);
            extra_short--;
        }
    }

    /* Discard original name if any */
    if (header.formatted.flags & 0x08)
        /* bit 3 set: original file name present */
        while(xread_char(src_fd) != 0) ;

    /* Discard file comment if any */
    if (header.formatted.flags & 0x10)
        /* bit 4 set: file comment present */
        while(xread_char(src_fd) != 0) ;

    /* Read the header checksum */
    if (header.formatted.flags & 0x02)
    {
        xread_char(src_fd);
        xread_char(src_fd);
    }
}
Exemplo n.º 3
0
int startup(u_short *port)
{
    int httpd = 0;
    struct sockaddr_in name;

    httpd = socket(PF_INET, SOCK_STREAM, 0);
    if (httpd == -1)
        error_die("socket");
    memset(&name, 0, sizeof(name));
    name.sin_family = AF_INET;
    name.sin_port = htons(*port);
    name.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0)
        error_die("bind");
    if (*port == 0) { /* if dynamically allocating a port */
        int namelen = sizeof(name);
        if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1)
            error_die("getsockname");
        *port = ntohs(name.sin_port);
    }
    if (listen(httpd, 5) < 0)
        error_die("listen");
    return(httpd);
}
Exemplo n.º 4
0
int open_target( char * file )
{
   if(!file)
      error_die("null arg",1);

   /* there's only 1 target */
   if( target_elf ) 
      free_elf( target_elf );

   if(!(target_elf = new_elf(file)))
      error_ret("can't open elf",-1);

#ifdef USE_COMMANDS
   /* check for info saved in xml file */
   if( use_info )
      if(open_target_info( target_elf ) < 0 )
         error_ret("problem getting info",-1);
#endif /* USE_COMMANDS */

   disasm_init();
   crunch_pltmap();
   gather_funcs_by_symtab( get_elf() );
   gather_funcs_by_section(NULL);
   get_objs_from_entry(get_elf());
   gather_vars( get_elf() );
   sync_func_map();

#if 0
   if( do_disasm || do_pltmap ||do_disasm_seg ||do_map_dmp){
      crunch_pltmap();
   }

   if( do_dump_funcs || do_disasm || do_disasm_seg || do_map_dmp ){
      gather_funcs_by_symtab( get_elf() );
      gather_funcs_by_section(NULL);
      get_objs_from_entry(get_elf());
   }
   if( do_vars || do_disasm || do_disasm_seg || do_map_dmp || do_map_dmp )
      gather_vars( get_elf() );
   sync_func_map();
#endif

   return(0);
}
Exemplo n.º 5
0
int main(void)
{
 int server_sock = -1;
 u_short port = 0;
 int client_sock = -1;
 struct sockaddr_in client_name;
 int client_name_len = sizeof(client_name);
 pid_t pid;
 //pthread_t newthread;

 //服务器启动,在指定端口或随机选取端口绑定 httpd 服务。
 server_sock = startup(&port);
 printf("httpd running on port %d\n", port);

 while (1)
 {
  //accept返回的是全新的描述符,代表与所返回客户的TCP连接。
  //server_sock是监听套接字,仅一个,服务器的生命期内一直存在
  client_sock = accept(server_sock,
                       (struct sockaddr *)&client_name,
                       &client_name_len);
  if (client_sock == -1)
   error_die("accept");
 printf("Receive a request from %s:%d\n" , inet_ntoa(client_name.sin_addr) , client_name.sin_port);
 if((pid = fork()) == 0)
 {  
    //因子进程也有指向server_sock文件的表项,且它不关心服务器套接字,它只处理客户套接字,因此close它
    //下面的父进程close client_sock也是同一个道理
    close(server_sock);
    accept_request(client_sock); 
    close(client_sock);
    exit(0);
 }
 int status = 0;
 pid_t pid2 = wait(&status);
 printf("My pid is %d\n", pid2);
 close(client_sock);
 //收到一个 HTTP 请求时(其实就是 listen 的端口 accpet 的时候),派生一个线程运行 accept_request 函数。
 // if (pthread_create(&newthread , NULL, accept_request, client_sock) != 0)
 //   perror("pthread_create");
}
 return(0);
}
Exemplo n.º 6
0
int main(void)
{
 int server_sock = -1; // 服务端socket描述符
 u_short port = 8089; // 端口号
 int client_sock = -1; // 客户端socket描述符
 struct sockaddr_in client_name; // 客户端地址结构
 socklen_t client_name_len = sizeof(client_name); // 客户端地址结构长度
 pthread_t newthread; // 线程ID

 server_sock = startup(&port); // 创建socket、绑定、监听、启动服务端
 printf("httpd running on port %d\n", port);
 
 char buf[INET_ADDRSTRLEN];

 // 在循环中不停接收客户连接
 // 每接受一个连接就开一个新的线程去处理
 while (1)
 {
  client_sock = accept(server_sock,
                       (struct sockaddr *)&client_name,
                       &client_name_len); // 阻塞等待客户端连接

  // const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
  printf("client connection (%s:%d)\n",
		 inet_ntop(AF_INET, &client_name.sin_addr, buf, INET_ADDRSTRLEN),
		 ntohs(client_name.sin_port));

  if (client_sock == -1)
   error_die("accept");
  /* accept_request(client_sock); */
  if (pthread_create(&newthread , NULL, accept_request, client_sock) != 0) // 开新线程处理
   perror("pthread_create");
 }

 close(server_sock); // 关闭服务端socket

 return(0);
}
Exemplo n.º 7
0
int main(int argc, char* argv[]){
    int server_sock = -1;
    u_short port = 4000;
    int client = -1;

    struct sockaddr_in client_name;
    socklen_t client_name_len = sizeof(client_name);
    pthread_t newthread;

    server_sock = startup(&port);
    printf("httpd running on port %d\n", port);
    
    while(1){
        client = accept(server_sock, (struct sockaddr *)&client_name, &client_name_len);
        if(client == -1){
            error_die("accpet");    
        }
        if(pthread_create(&newthread, NULL, (void *)accept_request, (void *)&client) != 0){
            perror("pthread_create");    
        }
    }
    close(server_sock);
    return 0;
}
Exemplo n.º 8
0
/**
 * @brief create a soocket
 *
 * @param domain [in] This value can be AF_INET,AF_UNIX,AF_LOCAL,
 *                    PF_INET, PF_UINX and PF_LOCAL.
 * @param type   [in] can be SOCK_TREAM, SOCK_DGRAM.
 *
 * @return socket fd, if succ; -1, if failed.
 */
int socket_create(int domain, int type)
{
    int fd = socket(domain, type, 0);
    if (fd == -1) error_die("socket");
    return fd;
}
Exemplo n.º 9
0
/**
 * @brief  listening for an incoming connect.
 *
 * @param fd      [in] listen socket fd.
 * @param backlog [in] Maximum length of the queue of pending connections.
 *
 * @return 0, if succ; -1, if failed.
 */
int socket_listen(int fd, int backlog)
{
    if (listen(fd, backlog) < 0) error_die("listen");

    return 0;
}
Exemplo n.º 10
0
int main (int argc, char *argv[])
{
    // double legit;
    srand48(time(NULL)); // Seed RNG
    char *buffer = NULL; // A buffer for the received data
    long bufsize = 0;
    FILE* outfile;

    if (argc != 6)
    {
        printf("Arg count was %d.\n", argc);
        usage_err();
    }

    // For statistical purposes
    int corrupt_count = 0;
    int loss_count = 0;

    int sockfd, portnum, bytes_recv, bytes_sent;
    int lost_packet = 0;

    socklen_t sin_size;

    struct sockaddr_in srv_addr;
    struct hostent *host;
    
    // Send data
    struct gbnpacket send_data;
    // Receive data
    struct gbnpacket recv_data;
    // recv_data.length = p_size();
    // recv_data.sequence = 0;

    // Parse command line arguments
    host = (struct hostent *) gethostbyname(argv[1]);
    portnum = atoi(argv[2]);
    char* filename = argv[3];
    printf("Filename is %s\n", filename);
    double p_loss = atof(argv[4]); // Probability of packet loss
    double p_corr = atof(argv[5]); // Probability of packet corruption

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
        error_die("Error opening socket.\n");
    
    // Initialize server address
    srv_addr.sin_family = AF_INET;
    srv_addr.sin_port = htons(portnum);
    srv_addr.sin_addr = *((struct in_addr *)host->h_addr);
    bzero(&(srv_addr.sin_zero),8);
    sin_size = sizeof(struct sockaddr);

    //------------------------------------
    // SEND request for file
    //------------------------------------
    memset(&send_data, 0, sizeof(struct gbnpacket));
    send_data.type = REQUEST;
    send_data.sequence = 0;
    send_data.corrupt = 0;
    strcpy(send_data.data, filename); // Might have to \0 out the last byte of data...not sure yet
    // send_data.data[strlen(filename)] = '\0';
    // send_data.length = p_header_size() + strlen(filename) + 1; // +1 for the null byte?
    send_data.length = strlen(filename);
    printf("Sending request to CS118 for %s\n", filename);
    long expecting_packet = 0; // The sequence number of the expected packet
    while (1)
    {
        if (send_data.type == REQUEST)
        {
            // Send
            // Convert to network byte order
            convertpacket_hton(&send_data);
            // bytes_sent = sendto(sockfd, &send_data, send_data.length, 0,
            bytes_sent = sendto(sockfd, &send_data, sizeof(struct gbnpacket), 0,
                            (struct sockaddr *)&srv_addr, sizeof(struct sockaddr));
                        // TO-DO: Check to see if bytes_sent matches up with the length of the packet in total.
            // buffer = NULL;
            print_packet_info_client(&send_data, CLIENT);
            // printf("Request sent.\n");
        }

        // --------------------------------
        // RECEIVE data response
        // --------------------------------
        printf("Waiting for response from CS118.\n");
        // bytes_recv = recvfrom(sockfd, &recv_data, recv_data.length, 0,
        bytes_recv = recvfrom(sockfd, &recv_data, sizeof(struct gbnpacket), 0, 
                        (struct sockaddr*)&srv_addr, &sin_size);
        // Convert to host byte order
        convertpacket_ntoh(&recv_data);
        
        // Set packet lost or not
        lost_packet = play_the_odds(p_loss, &loss_count);
        if (lost_packet)
        {
            printf("\nLOST PACKET!\n\n");
            continue; // Do nothing else, just receive the packet and move on.
        }
        // TO-DO: CHECK TO MAKE SURE THAT THE PROGRAM DOESN'T SEGFAULT IF recvfrom() FAILS! i.e. if bytesrecv == 0
        // recv_data.data[bytes_recv] = '\0';
        print_packet_info_client(&recv_data, SERVER);
        // printf("Received : %s\n", recv_data.data);

        // --------------------------------
        // PREPARE acknowledgement
        // --------------------------------
        if (recv_data.type == FIN)
        {
            // Send a FIN in return, and end the client process
            char *msg = "Terminating connection.";
            memset(&send_data, 0, sizeof(struct gbnpacket));
            send_data.type = FIN;
            send_data.sequence = 0;
            send_data.corrupt = 0; // set_packet_corruption();
            send_data.length = 0;
            // Don't need to initialize the data because of the memset
            printf("%s. Sending FIN packet.\n", msg);
            printf("STATS: Sent %d corrupt ACKs. Treated %d packets as \'lost\'.\n",
                            corrupt_count, loss_count);
            // Convert to network byte order
            convertpacket_hton(&send_data);
            /*
            send_data.type = htonl(send_data.type);
            send_data.sequence = htonl(send_data.sequence);
            send_data.length = htonl(send_data.length);
            */
            bytes_sent = sendto(sockfd, &send_data, sizeof(struct gbnpacket), 0, 
                            (struct sockaddr *)&srv_addr, sizeof(struct sockaddr));

            // Modify the filename
            strcat(filename, ".received");
            outfile = fopen(filename, "wb");
            if (outfile)
            {
                fwrite(buffer, bufsize, 1, outfile);
                printf("Successfully wrote buffer to file \"%s\"\n.", filename);
            }
            else
                error_die("Error writing buffer to file.");

            return 0; // End the client process
        }
        if (!buffer)
        {
            bufsize = sizeof(char) * recv_data.total_length;
            buffer = (char *)malloc(bufsize);
            if (!buffer)
                error_die("Not enough space for client file buffer.");
        }
        memset(&send_data, 0, sizeof(struct gbnpacket));
        send_data.type = ACK;
        // strcpy(send_data.data, "Acknowledged.");
        // send_data.data[strlen(send_data.data)] = '\0'; // Zero byte
        // send_data.length = p_header_size() + strlen(send_data.data) + 1; // Might need +1 for zero byte
        send_data.length = 0; // ACKs have no data
        // send_data.corrupt = 0;
        // send_data.corrupt = set_packet_corruption(p_corr);
        // ----------------------------------------------------------------
        // SEND acknowledgement, depending on the last packet received.
        // ----------------------------------------------------------------
        // Packet is legit
        if (recv_data.corrupt == 0 && recv_data.sequence <= expecting_packet) // Use <= for duplicate packets
        {
            // Copy file data into the buffer
            memcpy(buffer+recv_data.sequence, recv_data.data, recv_data.length);
            // send_data.sequence = recv_data.sequence + (bytes_recv - p_header_size());
            send_data.sequence = recv_data.sequence + PACKETSIZE;
            send_data.corrupt = play_the_odds(p_corr, &corrupt_count);

            // Convert to network byte order
            /*
            send_data.type = htonl(send_data.type);
            send_data.sequence = htonl(send_data.sequence);
            send_data.length = htonl(send_data.length);
            */
            // expecting_packet = recv_data.sequence + PACKETSIZE;
            expecting_packet = send_data.sequence;
            // Send
            // printf("Sending acknowledgement from else...\n");
            // sendto(sockfd, &send_data, send_data.length, 0, 

//            if (legit >= p_loss)
//            {
            // Convert to network byte order
            convertpacket_hton(&send_data);
            
            sendto(sockfd, &send_data, sizeof(struct gbnpacket), 0, 
                    (struct sockaddr *)&srv_addr, sizeof(struct sockaddr));
            print_packet_info_client(&send_data, CLIENT);
//            }
        }
        // else if (recv_data.corrupt == 0 && recv_data.sequence < expecting_packet)
        // {
        //     printf("\nDUPLICATE PACKET, IGNORING!\n\n");
        //     continue; // DUPLICATE PACKET
        // }
        // if (recv_data.sequence != expecting_packet || recv_data.corrupt == 1) // Packet received OUT OF ORDER or is CORRUPT
        else // Packet is not legit
        {
            // Be sure to send duplicate ACKs? Not in the book
            // The ACK should be for the last correctly-received packet.
            send_data.sequence = expecting_packet;
            send_data.corrupt = play_the_odds(p_corr, &corrupt_count);
            // Send
            // printf("Sending acknowledgement from if...\n");
            // sendto(sockfd, &send_data, send_data.length, 0, 
//            if (legit >= p_loss)
//            {
            // Convert to network byte order
            /*
            send_data.type = htonl(send_data.type);
            send_data.sequence = htonl(send_data.sequence);
            send_data.length = htonl(send_data.length);
            send_data.corrupt = htonl(send_data.corrupt);
            */
            convertpacket_hton(&send_data);
            sendto(sockfd, &send_data, sizeof(struct gbnpacket), 0, 
                        (struct sockaddr *)&srv_addr, sizeof(struct sockaddr));
            print_packet_info_client(&send_data, CLIENT);
//            }

        }


    }
    

    return 0;
}
Exemplo n.º 11
0
/*
处理客户端发送过来的请求,主要是判断请求是get还是post方法
把 请求方法 url protocol 进行分离
并判断是请求静态内容还是cgi
分别调用deal_static和deal_cgi进行处理
*/
void deal_request(void *client_sock){
	
	//客户端sock号
	int cli_sock =*(int*)client_sock;
	int charnum=0;
	char buf[1024];
	//请求方法
	char method[10];
	char url[255];
	char protocol[50];
	bool cgi=false;
	//cgi程序的参数
	char *query_string=NULL;
	char *path=NULL;
	//文件的各种信息,具体可以查看stat函数
	struct stat st;
	
	//读取一行
	charnum=get_line(cli_sock,buf,sizeof(buf));
	if(charnum==0){
		error_die("get_line error\n");
	}
	
	//进行分离
	if(EOF==sscanf(buf,"%[^ ] %[^ ] %[^ ]",method,url,protocol)){
		error_die("sscanf error");
	}

	//method is not get and post
	if((strcasecmp(method,"GET")!=0)&&(strcasecmp(method,"POST")!=0)){
		
		uncompleted(cli_sock,method);
		return;
	}
	
	if(strcasecmp(method,"POST")==0){	
		cgi=true;
	}

	if(strcasecmp(method,"GET")==0){
		//找出?字符的位置
		query_string=strchr(url,'?');
		if(query_string){
			cgi=true;
			*query_string='\0';
			query_string++;
		}

		//如果是get方法,后面的内容没有用,就丢弃
		charnum=get_line(cli_sock,buf,sizeof(buf));
		while((charnum>0)&&strcmp("\n",buf)){
			//printf("%s",buf);
			charnum=get_line(cli_sock,buf,sizeof(buf));

		}
	}
	//url的形式为:/aisi.jpg,而path是存取路径,把第一个/去掉,变为aisi.jpg
	path=url+1;
	//判断文件是否存在
	if(stat(path,&st)==-1){
		not_found(cli_sock,path);
	}else{
		//如果访问的是目录,默认为访问主页
		if((st.st_mode&S_IFMT)==S_IFDIR){
			sprintf(path,"index.html");
		}
		//查看是否有执行权限,如果有,就是cgi
		if((st.st_mode&S_IXOTH)||(st.st_mode&S_IXUSR)||(st.st_mode&S_IXGRP)){
			cgi=true;
		}
		//分别调用对应的处理函数
		if(cgi){
			deal_cgi(cli_sock,path,method,query_string);
		}else{
			deal_static(cli_sock,path,(int)st.st_size);
		}
	
	}

	close(cli_sock);

}
Exemplo n.º 12
0
static int inflate_codes(huft_t * my_tl, huft_t * my_td,
                         const unsigned int my_bl, const unsigned int my_bd,
                         int setup)
{
    static unsigned int e;        /* table entry flag/number of extra bits */
    static unsigned int n, d;    /* length and index for copy */
    static unsigned int w;        /* current gunzip_window position */
    static huft_t *t;            /* pointer to table entry */
    static unsigned int ml, md;    /* masks for bl and bd bits */
    static unsigned int b;        /* bit buffer */
    static unsigned int k;        /* number of bits in bit buffer */
    static huft_t *tl, *td;
    static unsigned int bl, bd;

    if (setup)   /* 1st time we are called, copy in variables */
    {
        tl = my_tl;
        td = my_td;
        bl = my_bl;
        bd = my_bd;
        /* make local copies of globals */
        b = gunzip_bb;                /* initialize bit buffer */
        k = gunzip_bk;
        w = gunzip_outbuf_count;            /* initialize gunzip_window position
                                             */

        /* inflate the coded data */
        ml = mask_bits[bl];    /* precompute masks for speed */
        md = mask_bits[bd];
        return 0; /* Don't actually do anything the first time */
    }

    if (inflate_codes_resumeCopy) goto do_copy;

    while (1)              /* do until end of block */
    {
        b = fill_bitbuffer(b, &k, bl);
        if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
            do {
                if (e == 99)
                    error_die("inflate_codes error 1");

                b >>= t->b;
                k -= t->b;
                e -= 16;
                b = fill_bitbuffer(b, &k, e);
            } while ((e =
                          (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);

        b >>= t->b;
        k -= t->b;
        if (e == 16)      /* then it's a literal */
        {
            gunzip_window[w++] = (unsigned char) t->v.n;
            if (w == gunzip_wsize)
            {
                gunzip_outbuf_count = (w);
                w = 0;
                return 1; /* We have a block to read */
            }
        }
        else            /* it's an EOB or a length */
        {   /* exit if end of block */
            if (e == 15)
                break;

            /* get length of block to copy */
            b = fill_bitbuffer(b, &k, e);
            n = t->v.n + ((unsigned) b & mask_bits[e]);
            b >>= e;
            k -= e;

            /* decode distance of block to copy */
            b = fill_bitbuffer(b, &k, bd);
            if ((e = (t = td + ((unsigned) b & md))->e) > 16)
                do {
                    if (e == 99)
                        error_die("inflate_codes error 2");

                    b >>= t->b;
                    k -= t->b;
                    e -= 16;
                    b = fill_bitbuffer(b, &k, e);
                } while ((e =
                              (t =
                                   t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);

            b >>= t->b;
            k -= t->b;
            b = fill_bitbuffer(b, &k, e);
            d = w - t->v.n - ((unsigned) b & mask_bits[e]);
            b >>= e;
            k -= e;

            /* do the copy */
do_copy:        do {
                n -= (e =
                          (e =
                               gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e);
                /* copy to new buffer to prevent possible overwrite */
                if (w - d >= e)      /* (this test assumes unsigned comparison)
                                      */
                {
                    memcpy(gunzip_window + w, gunzip_window + d, e);
                    w += e;
                    d += e;
                }
                else
                {
                    /* do it slow to avoid memcpy() overlap */
                    /* !NOMEMCPY */
                    do {
                        gunzip_window[w++] = gunzip_window[d++];
                    } while (--e);
                }

                if (w == gunzip_wsize)
                {
                    gunzip_outbuf_count = (w);
                    if (n) inflate_codes_resumeCopy = 1;
                    else inflate_codes_resumeCopy = 0;

                    w = 0;
                    return 1;
                }
            } while (n);
            inflate_codes_resumeCopy = 0;
        }
    }

    /* restore the globals from the locals */
    gunzip_outbuf_count = w;    /* restore global gunzip_window pointer */
    gunzip_bb = b;                /* restore global bit buffer */
    gunzip_bk = k;

    /* normally just after call to inflate_codes, but save code by putting it
       here */
    /* free the decoding tables, return */
    huft_free(tl,HUFT_MMP1);
    huft_free(td,HUFT_MMP2);

    /* done */
    return 0;
}
Exemplo n.º 13
0
int main(void) {

    int i;
    int ifd;
    int len;
    int client_sock;
    struct online_user *user;
    Client client;
    struct sockaddr_in client_name;
    int client_name_len = sizeof(client_name);
#define MAX_BUFSIZE	0x100000
    char buf[MAX_BUFSIZE];
    struct format *package = (struct format *)buf;

    tcp_server_sock = tcp_startup(SERVER_TCP_PORT);

    init_mysql();
    register_ctrl_c();

    kdpfd = epoll_create(MAXEPOLLSIZE);

    /* 设置要监听的事件。EPOLLIN 表示可读,EPOLLET则指定电平触发 */
    ev.events = EPOLLIN;
    ev.data.fd = tcp_server_sock;

    if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, tcp_server_sock, &ev) < 0)
        /* 把 tcp sock 加入监听集合,以便接收连接请求 */
        error_die("tcp epoll_ctl\n");

    /* 记录监听的文件数,同时他也是 epoll_wait 的第三个参数。
       因为内核需要知道 events 数组的有效数据有多长 */
    curfds = 1;

    for (;;) {

        memset(buf,0,sizeof(buf));
        printf("waiting...\n");

        /* 等待有事件发生。该函数的返回值存放在 nfds 和 events 内 */
        nfds = epoll_wait(kdpfd, events, curfds, -1);

        if (nfds < 0)
            error_die("epoll_wait");

        for (i = 0; i < nfds; i++) {

            ifd = events[i].data.fd;

            if (ifd == tcp_server_sock) {
                //新的 TCP 连接请求到来

                if (!(events[i].events & EPOLLIN))
                    error_die("failed to event is not EPOLLIN\n");

                client_sock = accept(tcp_server_sock,(struct sockaddr *)&client_name,&client_name_len);
                setnonblocking(client_sock);

                ev.events  = EPOLLIN;
                ev.data.fd = client_sock;
                if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client_sock, &ev) < 0)
                    error_die("epoll_ctl");

                curfds++;

                client = alloc_client(client_sock);
                add_client(client);

            } else if ((events[i].events & EPOLLIN)) {
                /* 客户端有数据发来(POLLIN)或者发生 POLLHUP/POLLERR(这两个事件系统会自动监听) */

                client = find_client(ifd);

                if (client != NULL && client->handler != NULL) {
                    //已经有了处理函数,直接调用这个函数来处理
                    client->handler(ifd,client->private);
                } else {
                    //默认的处理方法

                    //读入数据包头部。
                    len = read(ifd,package,(sizeof(struct format)-sizeof(package->data)));

                    if (len <= 0) {
                        //对方断线。
                        close_connect(ifd);
                        continue;
                    }

                    if (package->length >= MAX_BUFSIZE || package->length <= 0) {

                        while(read(ifd,package->data,4) > 0);
                        continue;
                    }

                    if ((len = read(ifd,package->data,package->length) <= 0)) {
                        //读入数据包内容

                        close_connect(ifd);
                        continue;
                    }

                    // 处理数据
                    if (handle(ifd,package) == NEED_WRITE) {

                        ev.events = EPOLLOUT;
                        ev.data.fd = ifd;
                        epoll_ctl(kdpfd,EPOLL_CTL_MOD,ifd,&ev);
                    }
                }

            } else if(events[i].events & EPOLLOUT) {
Exemplo n.º 14
0
void *GallocyServer::work() {
  LOG_DEBUG("Starting HTTP server on " << address << ":" << port);

  struct sockaddr_in name;
  int optval = 1;

  server_socket = socket(PF_INET, SOCK_STREAM, 0);
  if (server_socket == -1) {
    error_die("socket");
  }

#ifdef __APPLE__
  setsockopt(server_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
#else
  setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
#endif

  memset(&name, 0, sizeof(name));
  name.sin_family = AF_INET;
  name.sin_port = htons(port);
  // name.sin_addr.s_addr = htonl(INADDR_ANY);
  name.sin_addr.s_addr = inet_addr(address.c_str());

  if (bind(server_socket, (struct sockaddr *) &name, sizeof(name)) < 0) {
    error_die("bind");
  }

  if (listen(server_socket, 5) < 0) {
    error_die("listen");
  }

  int64_t client_sock = -1;
  struct sockaddr_in client_name;
  uint64_t client_name_len = sizeof(client_name);
  pthread_t newthread;

  while (alive) {
    client_sock = accept(server_socket,
        reinterpret_cast<struct sockaddr *>(&client_name),
        reinterpret_cast<socklen_t *>(&client_name_len));

    if (client_sock == -1) {
      error_die("accept");
    }

    struct RequestContext *ctx =
      new (internal_malloc(sizeof(struct RequestContext))) struct RequestContext;
    ctx->server = this;
    ctx->client_socket = client_sock;
    ctx->client_name = client_name;

    if (get_pthread_create_impl()(&newthread, NULL, handle_entry, reinterpret_cast<void *>(ctx)) != 0) {
      perror("pthread_create1");
    }

    // TODO(sholsapp): This shouldn't block, and we shouldn't just try to
    // join this thread.
    if (get_pthread_join_impl()(newthread, nullptr)) {
      perror("pthread_join1");
    }
  }

  close(server_socket);

  return nullptr;
}