├── ip.txt ├── README.md ├── .gitignore ├── a.txt ├── t1.c ├── malloc.c ├── LICENSE ├── ip-whois.c ├── replace-1.c ├── logtest.c ├── epoll_server2.c ├── processtitle.c ├── myepoll.c ├── epoll-example.c ├── epoll_server.c ├── epoll_poll.c ├── sockevent.c ├── httpv.c └── t2.c /ip.txt: -------------------------------------------------------------------------------- 1 | 220.181.111.188 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | c-example 2 | ========= 3 | 4 | example code 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Libraries 8 | *.lib 9 | *.a 10 | 11 | # Shared objects (inc. Windows DLLs) 12 | *.dll 13 | *.so 14 | *.so.* 15 | *.dylib 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.i*86 22 | *.x86_64 23 | *.hex 24 | -------------------------------------------------------------------------------- /a.txt: -------------------------------------------------------------------------------- 1 | 0x60f6c0,0 2 | HTTP/1.1 200 OK 3 | Server: hhhh 4 | Date: Tue, 05 Aug 2014 07:56:25 GMT 5 | Last-Modified: Sat, 27 Apr 2013 04:12:05 GMT 6 | Content-Type: text/html 7 | Content-Length: 155 8 | Connection: close 9 | 10 | 11 | 301 Moved 12 |

Hello World!

13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /t1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | char str[] = "1.1.1.1"; 6 | char aa[10][16] = {0}; 7 | char *p; 8 | char *buff; 9 | buff=str; 10 | p = strsep(&buff, ","); 11 | int i = 0; 12 | while(p) 13 | { 14 | strcpy(aa[i] , p); 15 | printf("%s\n", p); 16 | p = strsep(&buff, ","); 17 | ++i; 18 | } 19 | for (i = 0; i < 10; ++i) 20 | { 21 | if(strlen(aa[i]) >= 7) 22 | printf("aa[%d]=%s\n", i, aa[i] ); 23 | } 24 | for (i = 0; i < 10; ++i) 25 | { 26 | if(strlen(aa[i]) >= 7) 27 | printf("aa[%d]=%s\n", i, aa[i] ); 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | 6 | void * 7 | debug_malloc(size_t size, const char *file, int line, const char *func) 8 | { 9 | void *p; 10 | 11 | p = malloc(size); 12 | printf("%s:%d:%s:malloc(%ld): p=0x%lx\n", 13 | file, line, func, size, (unsigned long)p); 14 | return p; 15 | } 16 | 17 | #define malloc(s) debug_malloc(s, __FILE__, __LINE__, __func__) 18 | #define free(p) do { \ 19 | printf("%s:%d:%s:free(0x%lx)\n", __FILE__, __LINE__, \ 20 | __func__, (unsigned long)p); \ 21 | free(p); \ 22 | } while (0) 23 | 24 | int 25 | main(int argc, char *argv[]) 26 | { 27 | char *p; 28 | p = malloc(1024); 29 | free(p); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 millken 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ip-whois.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @brief 3 | * Whois client program 4 | * 5 | * @details 6 | * This program shall fetch whois data for a IPv4 address. 7 | * 8 | * @author Silver Moon ( m00n.silv3r@gmail.com ) 9 | * http://www.binarytides.com/c-code-to-perform-ip-whois/ 10 | * */ 11 | 12 | #include //scanf , printf 13 | #include //strtok 14 | #include //realloc 15 | #include //socket 16 | #include //sockaddr_in 17 | #include //getsockname 18 | #include //hostent 19 | #include //close 20 | 21 | int main(int argc , char *argv[]) 22 | { 23 | char ip[100] , *data = NULL; 24 | 25 | printf("Enter ip address to whois : "); 26 | scanf("%s" , ip); 27 | 28 | get_whois(ip , &data); 29 | printf("\n\n"); 30 | puts(data); 31 | 32 | free(data); 33 | return 0; 34 | } 35 | 36 | /** 37 | Get the whois content of an ip 38 | by selecting the correct server 39 | */ 40 | void get_whois(char *ip , char **data) 41 | { 42 | char *wch = NULL, *pch , *response = NULL; 43 | 44 | if(whois_query("whois.iana.org" , ip , &response)) 45 | { 46 | printf("Whois query failed"); 47 | } 48 | 49 | pch = strtok(response , "\n"); 50 | 51 | while(pch != NULL) 52 | { 53 | //Check if whois line 54 | wch = strstr(pch , "whois."); 55 | if(wch != NULL) 56 | { 57 | break; 58 | } 59 | 60 | //Next line please 61 | pch = strtok(NULL , "\n"); 62 | } 63 | 64 | if(wch != NULL) 65 | { 66 | printf("\nWhois server is : %s" , wch); 67 | whois_query(wch , ip , data); 68 | } 69 | else 70 | { 71 | *data = malloc(100); 72 | strcpy(*data , "No whois data"); 73 | } 74 | 75 | return; 76 | } 77 | 78 | /* 79 | * Perform a whois query to a server and record the response 80 | * */ 81 | int whois_query(char *server , char *query , char **response) 82 | { 83 | char ip[32] , message[100] , buffer[1500]; 84 | int sock , read_size , total_size = 0; 85 | struct sockaddr_in dest; 86 | 87 | sock = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP); 88 | 89 | //Prepare connection structures :) 90 | memset( &dest , 0 , sizeof(dest) ); 91 | dest.sin_family = AF_INET; 92 | 93 | printf("\nResolving %s..." , server); 94 | if(hostname_to_ip(server , ip)) 95 | { 96 | printf("Failed"); 97 | return 1; 98 | } 99 | printf("%s" , ip); 100 | dest.sin_addr.s_addr = inet_addr( ip ); 101 | dest.sin_port = htons( 43 ); 102 | 103 | //Now connect to remote server 104 | if(connect( sock , (const struct sockaddr*) &dest , sizeof(dest) ) < 0) 105 | { 106 | perror("connect failed"); 107 | } 108 | 109 | //Now send some data or message 110 | printf("\nQuerying for ... %s ..." , query); 111 | sprintf(message , "%s\r\n" , query); 112 | if( send(sock , message , strlen(message) , 0) < 0) 113 | { 114 | perror("send failed"); 115 | } 116 | 117 | //Now receive the response 118 | while( (read_size = recv(sock , buffer , sizeof(buffer) , 0) ) ) 119 | { 120 | *response = realloc(*response , read_size + total_size); 121 | if(*response == NULL) 122 | { 123 | printf("realloc failed"); 124 | } 125 | memcpy(*response + total_size , buffer , read_size); 126 | total_size += read_size; 127 | } 128 | printf("Done"); 129 | fflush(stdout); 130 | 131 | *response = realloc(*response , total_size + 1); 132 | *(*response + total_size) = '\0'; 133 | 134 | close(sock); 135 | return 0; 136 | } 137 | 138 | /* 139 | * @brief 140 | * Get the ip address of a given hostname 141 | * 142 | * */ 143 | int hostname_to_ip(char * hostname , char* ip) 144 | { 145 | struct hostent *he; 146 | struct in_addr **addr_list; 147 | int i; 148 | 149 | if ( (he = gethostbyname( hostname ) ) == NULL) 150 | { 151 | // get the host info 152 | herror("gethostbyname"); 153 | return 1; 154 | } 155 | 156 | addr_list = (struct in_addr **) he->h_addr_list; 157 | 158 | for(i = 0; addr_list[i] != NULL; i++) 159 | { 160 | //Return the first one; 161 | strcpy(ip , inet_ntoa(*addr_list[i]) ); 162 | return 0; 163 | } 164 | 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /replace-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | //http://creativeandcritical.net/str-replace-c/ 9 | char *replace_str(const char *str, const char *old, const char *new) 10 | { 11 | char *ret, *r; 12 | const char *p, *q; 13 | size_t oldlen = strlen(old); 14 | size_t count, retlen, newlen = strlen(new); 15 | 16 | if (oldlen != newlen) { 17 | for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) 18 | count++; 19 | /* this is undefined if p - str > PTRDIFF_MAX */ 20 | retlen = p - str + strlen(p) + count * (newlen - oldlen); 21 | } else 22 | retlen = strlen(str); 23 | 24 | if ((ret = malloc(retlen + 1)) == NULL) 25 | return NULL; 26 | 27 | for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) { 28 | /* this is undefined if q - p > PTRDIFF_MAX */ 29 | ptrdiff_t l = q - p; 30 | memcpy(r, p, l); 31 | r += l; 32 | memcpy(r, new, newlen); 33 | r += newlen; 34 | } 35 | strcpy(r, p); 36 | 37 | return ret; 38 | } 39 | 40 | int random_int(int min, int max) 41 | { 42 | /* Seed number for rand() */ 43 | struct timeb t; 44 | ftime(&t); 45 | srand((unsigned int) 1000 * t.time + t.millitm + random()); 46 | //srandom( time(0)+clock()+random() ); 47 | unsigned int s_seed = 214013 * rand() + 2531011; 48 | return min+(s_seed ^ s_seed>>15)%(max-min+1); 49 | } 50 | 51 | //http://www.cnblogs.com/chenyuming507950417/archive/2012/01/02/2310114.html 52 | char *replace_ip(const char *str, const char *old) 53 | { 54 | char *ret, *r; 55 | const char *p, *q; 56 | size_t oldlen = strlen(old); 57 | size_t count, retlen, newlen = 4; 58 | 59 | char ip[3]; 60 | for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) 61 | count++; 62 | /* this is undefined if p - str > PTRDIFF_MAX */ 63 | retlen = p - str + strlen(p) + count * (newlen - oldlen); 64 | if ((ret = malloc(retlen + 1)) == NULL) 65 | return NULL; 66 | 67 | for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) { 68 | /* this is undefined if q - p > PTRDIFF_MAX */ 69 | ptrdiff_t l = q - p; 70 | memcpy(r, p, l); 71 | r += l; 72 | bzero(ip, newlen); 73 | sprintf(ip, "%d", random_int(1, 255)); 74 | newlen = strlen(ip); 75 | printf("%s=%d\n", ip, newlen); 76 | memcpy(r, ip, newlen); 77 | r += newlen; 78 | } 79 | strcpy(r, p); 80 | return ret; 81 | } 82 | 83 | char * 84 | random_chars(char *dst, int start, int end) 85 | { 86 | srandom( time(0)+clock()+random() ); //生成更好的随机数 87 | static const char allowable_chars[] = "1234567890abcdefhijklnmopqrstuwxyz"; 88 | int i, r; 89 | int size = rand()%(end - start + 1) + start;/*n为a~b之间的随机数*/ 90 | for (i = 0; i< size; i++) { 91 | r = (int)((double)rand() / ((double)RAND_MAX + 1) * (sizeof(allowable_chars) -1 )); 92 | dst[i] = allowable_chars[r]; 93 | } 94 | dst[i] = '\0'; 95 | 96 | return dst; 97 | } 98 | 99 | char * 100 | replace_domain(const char *str, const char *old) 101 | { 102 | char *ret, *r; 103 | const char *p, *q; 104 | size_t oldlen = strlen(old); 105 | size_t count, retlen, newlen = 26; 106 | 107 | char s[25]; 108 | for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) 109 | count++; 110 | /* this is undefined if p - str > PTRDIFF_MAX */ 111 | retlen = p - str + strlen(p) + count * (newlen - oldlen); 112 | if ((ret = malloc(retlen + 1)) == NULL) 113 | return NULL; 114 | 115 | for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) { 116 | /* this is undefined if q - p > PTRDIFF_MAX */ 117 | ptrdiff_t l = q - p; 118 | memcpy(r, p, l); 119 | r += l; 120 | bzero(s, newlen); 121 | random_chars(s, 5, 25); 122 | newlen = strlen(s); 123 | printf("%s=%d\n", s, newlen); 124 | memcpy(r, s, newlen); 125 | r += newlen; 126 | } 127 | strcpy(r, p); 128 | return ret; 129 | } 130 | 131 | int main(int argc, char **argv) 132 | { 133 | char *s1, *s2, *s3, *d1, *d2; 134 | s1 = "1.*.33.*"; 135 | d1 = "*.*.com"; 136 | printf("%d\n", random_int(1, 300)); 137 | 138 | s2 = replace_str(s1, "*", "23"); 139 | printf("s2=%s\n", s2); 140 | 141 | s3 = replace_ip(s1, "*"); 142 | printf("s3=%s\n", s3); 143 | 144 | d2 = replace_domain(d1, "*"); 145 | printf("d2=%s\n", d2); 146 | } 147 | -------------------------------------------------------------------------------- /logtest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include //va_start va_end 6 | //#include 7 | 8 | #define FG_WHITE "\x1B[0;m" /* white */ 9 | #define FG_RED "\033[0;31m" /* 0 -> normal ; 31 -> red */ 10 | #define FG_RED_BOLD "\033[1;31m" /* 1 -> bold ; 31 -> red */ 11 | #define FG_GREEN "\033[0;32m" /* 4 -> underline ; 32 -> green */ 12 | #define FG_GREEN_BOLD "\033[1;32m" 13 | #define FG_YELLOW "\033[0;33m" /* 0 -> normal ; 33 -> yellow */ 14 | #define FG_YELLOW_BOLD "\033[1;33m" 15 | #define FG_BLUE "\033[0;34m" /* 9 -> strike ; 34 -> blue */ 16 | #define FG_BLUE_BOLD "\033[1;34m" 17 | #define FG_CYAN "\033[0;36m" /* 0 -> normal ; 36 -> cyan */ 18 | #define FG_CYAN_BOLD "\033[0;36m" 19 | #define FG_DEFAULT "\033[39m" 20 | #define BG_RED "\033[41m" 21 | #define BG_GREEN "\033[42m" 22 | #define BG_BLUE "\033[44m" 23 | #define BG_DEFAULT "\033[49m" 24 | #define RESET_COLOR "\033[0m" /* to flush the previous property */ 25 | 26 | #define LOG_INFO (1<<0) //1 27 | #define LOG_WARN (1<<1) //2 28 | #define LOG_ERROR (1<<2) //4 29 | #define LOG_DEBUG (1<<3) //8 30 | #define LOG_ALL ((2<<16)-1) 31 | 32 | #define INFO(f...) do { LOG_WRITER(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, f); } while (0) 33 | #define WARN(f...) do { LOG_WRITER(LOG_WARN, __FILE__, __FUNCTION__, __LINE__, f); } while (0) 34 | #define ERROR(f...) do { LOG_WRITER(LOG_ERROR, __FILE__, __FUNCTION__, __LINE__, f); } while (0) 35 | #define DEBUG(f...) do { LOG_WRITER(LOG_DEBUG, __FILE__, __FUNCTION__, __LINE__, f); } while (0) 36 | #define DBG(l,f...) do { LOG_WRITER(l, __FILE__, __FUNCTION__, __LINE__, f); } while (0) 37 | 38 | #define LOG_MAX_MSG_LEN 4098 39 | 40 | static void *_20131025_log_device = NULL; 41 | static int _20131025_log_level = 1; 42 | 43 | extern void LOG_INIT(const char *device); 44 | const char* LOG_SET_COLOR(int level, int is_end); 45 | extern void LOG_DESTORY(); 46 | extern void LOG_LEVEL(); 47 | static void LOG_ADD(int level, const char *file, const char * func, int line, const char *msg); 48 | static void LOG_WRITER(int level, const char *file, const char * func, int line, const char *fmt, ...); 49 | 50 | void LOG_INIT(const char *device) 51 | { 52 | _20131025_log_device = !device ? stdout : fopen((const char *)device, "a+"); 53 | } 54 | const char* LOG_SET_COLOR(int level, int is_end) 55 | { 56 | if (_20131025_log_device == stdout) { 57 | if (is_end) { 58 | return RESET_COLOR; 59 | } else { 60 | switch (level) { 61 | case LOG_INFO : return FG_DEFAULT; break; 62 | case LOG_WARN : return FG_YELLOW; break; 63 | case LOG_ERROR : return FG_RED; break; 64 | case LOG_DEBUG : return FG_CYAN; break; 65 | default : return FG_BLUE_BOLD; break; 66 | } 67 | } 68 | } 69 | return ""; 70 | } 71 | 72 | void LOG_DESTORY() 73 | { 74 | if (_20131025_log_device != stdout) fclose(_20131025_log_device); 75 | } 76 | 77 | void LOG_LEVEL(int level) 78 | { 79 | _20131025_log_level = level; 80 | } 81 | 82 | 83 | static void LOG_ADD(int level, const char *file, const char * func, int line, const char *msg) 84 | { 85 | const char *c = "IWEDX"; 86 | const char *datetime_format = "%Y-%m-%d %H:%M:%S"; 87 | time_t meow = time( NULL ); 88 | char buf[64]; 89 | int cl = 0; 90 | 91 | if ((level & ~_20131025_log_level) != 0 ) return; 92 | //cl = floor(log(level)/log(2)) + 1; 93 | switch (level) { 94 | case LOG_INFO : cl = 0; break; 95 | case LOG_WARN : cl = 1; break; 96 | case LOG_ERROR : cl = 2; break; 97 | case LOG_DEBUG : cl = 3; break; 98 | default : cl = 4; break; 99 | } 100 | 101 | strftime( buf, sizeof(buf), datetime_format, localtime(&meow) ); 102 | fprintf(_20131025_log_device, "%s%s[%d][%s(%s):%d] %c, %s%s\n",LOG_SET_COLOR(level, 0) , buf, (int)getpid(), file, func, line, c[cl], msg ,LOG_SET_COLOR(level, 1)); 103 | } 104 | 105 | static void LOG_WRITER(int level, const char *file, const char * func, int line, const char *fmt, ...) 106 | { 107 | va_list ap; 108 | char msg[LOG_MAX_MSG_LEN]; 109 | 110 | va_start(ap, fmt); 111 | vsnprintf(msg, sizeof(msg), fmt, ap); 112 | LOG_ADD(level, file, func, line, msg); 113 | va_end(ap); 114 | } 115 | 116 | int main(int argc, char *argv[]) 117 | { 118 | int j; 119 | LOG_INIT(NULL); 120 | //LOG_INIT("a.log"); 121 | LOG_LEVEL(1<<5); 122 | for ( j = 0; j < 2; j++ ) { 123 | INFO("INFO: %d", j); 124 | ERROR("ERROR: %d", j); 125 | DEBUG("DEBUG: %s", "dddd"); 126 | WARN("WARN: %d", j); 127 | DBG(32, "DBG: %d", j); 128 | } 129 | LOG_DESTORY(); 130 | //sleep(1); // you can ps now 131 | return 0; 132 | } 133 | 134 | -------------------------------------------------------------------------------- /epoll_server2.c: -------------------------------------------------------------------------------- 1 | //http://www.it165.net/os/html/201308/5868.html 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #define MAX_EVENTS 10 17 | #define PORT 823 18 | //设置socket连接为非阻塞模式 19 | void setnonblocking(int sockfd) { 20 | int opts; 21 | 22 | opts = fcntl(sockfd, F_GETFL); 23 | if(opts < 0) { 24 | perror("fcntl(F_GETFL)\n"); 25 | exit(1); 26 | } 27 | opts = (opts | O_NONBLOCK); 28 | if(fcntl(sockfd, F_SETFL, opts) < 0) { 29 | perror("fcntl(F_SETFL)\n"); 30 | exit(1); 31 | } 32 | } 33 | 34 | int main(){ 35 | struct epoll_event ev, events[MAX_EVENTS]; 36 | int addrlen, listenfd, conn_sock, nfds, epfd, fd, i, nread, n; 37 | struct sockaddr_in local, remote; 38 | char buf[BUFSIZ]; 39 | 40 | //创建listen socket 41 | if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 42 | perror("sockfd\n"); 43 | exit(1); 44 | } 45 | setnonblocking(listenfd); 46 | bzero(&local, sizeof(local)); 47 | local.sin_family = AF_INET; 48 | local.sin_addr.s_addr = htonl(INADDR_ANY);; 49 | local.sin_port = htons(PORT); 50 | if( bind(listenfd, (struct sockaddr *) &local, sizeof(local)) < 0) { 51 | perror("bind\n"); 52 | exit(1); 53 | } 54 | listen(listenfd, 20); 55 | 56 | epfd = epoll_create(MAX_EVENTS); 57 | if (epfd == -1) { 58 | perror("epoll_create"); 59 | exit(EXIT_FAILURE); 60 | } 61 | ev.events = EPOLLIN; 62 | ev.data.fd = listenfd; 63 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev) == -1) { 64 | perror("epoll_ctl: listen_sock"); 65 | exit(EXIT_FAILURE); 66 | } 67 | 68 | for (;;) { 69 | nfds = epoll_wait(epfd, events, MAX_EVENTS, -1); 70 | if (nfds == -1) { 71 | perror("epoll_pwait"); 72 | exit(EXIT_FAILURE); 73 | } 74 | 75 | for (i = 0; i < nfds; ++i) { 76 | fd = events[i].data.fd; 77 | if (fd == listenfd) { 78 | while ((conn_sock = accept(listenfd,(struct sockaddr *) &remote,(size_t *)&addrlen)) > 0) { 79 | setnonblocking(conn_sock); //设置连接socket为非阻塞 80 | ev.events = EPOLLIN | EPOLLET; //边沿触发要求套接字为非阻塞模式;水平触发可以是阻塞或非阻塞模式 81 | ev.data.fd = conn_sock; 82 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, conn_sock,&ev) == -1) { 83 | perror("epoll_ctl: add"); 84 | exit(EXIT_FAILURE); 85 | } 86 | } 87 | if (conn_sock == -1) { 88 | if (errno != EAGAIN && errno != ECONNABORTED && errno != EPROTO && errno != EINTR) 89 | perror("accept"); 90 | } 91 | continue; 92 | } 93 | if (events[i].events & EPOLLIN) { 94 | n = 0; 95 | while ((nread = read(fd, buf + n, BUFSIZ-1)) > 0) { 96 | n += nread; 97 | } 98 | if (nread == -1 && errno != EAGAIN) { 99 | perror("read error"); 100 | } 101 | ev.data.fd = fd; 102 | ev.events = events[i].events | EPOLLOUT; 103 | if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) == -1) { 104 | perror("epoll_ctl: mod"); 105 | } 106 | } 107 | if (events[i].events & EPOLLOUT) { 108 | sprintf(buf, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\nHello World", 11); 109 | int nwrite, data_size = strlen(buf); 110 | n = data_size; 111 | while (n > 0) { 112 | nwrite = write(fd, buf + data_size - n, n); 113 | if (nwrite < n) { 114 | if (nwrite == -1 && errno != EAGAIN) { 115 | perror("write error"); 116 | } 117 | break; 118 | } 119 | n -= nwrite; 120 | } 121 | close(fd); 122 | } 123 | } 124 | } 125 | close(epfd); 126 | close(listenfd); 127 | return 0; 128 | } 129 | -------------------------------------------------------------------------------- /processtitle.c: -------------------------------------------------------------------------------- 1 | //from alilua 2 | #define _GNU_SOURCE 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | //#include "setproctitle.h" 14 | char *process_char_last; 15 | char process_chdir[924]; 16 | char process_name[100]; 17 | char **_argv; 18 | int _argc; 19 | static int _signal_handler = 0; 20 | extern char **environ; 21 | extern void initproctitle (int argc, char **argv); 22 | extern void setProcTitle (const char *title, int is_master); 23 | void daemonize(); 24 | void signal_handler ( int sig ); 25 | void active_cpu ( uint32_t active_cpu ); 26 | //end h 27 | #ifdef linux 28 | 29 | static inline void print_cpu_mask ( cpu_set_t cpu_mask ) 30 | { 31 | uint8_t flag; 32 | uint32_t i; 33 | printf ( "%d Cpu affinity is ", getpid() ); 34 | flag = 0; 35 | 36 | for ( i = 0; i < sizeof ( cpu_set_t ); i ++ ) { 37 | if ( CPU_ISSET ( i, &cpu_mask ) ) { 38 | if ( flag == 0 ) { 39 | flag = 1; 40 | printf ( "%d", i ); 41 | 42 | } else { 43 | printf ( ",%d", i ); 44 | } 45 | } 46 | } 47 | 48 | printf ( ".\n" ); 49 | } 50 | 51 | static inline void get_cpu_mask ( pid_t pid, cpu_set_t *mask ) 52 | { 53 | if ( sched_getaffinity ( pid, sizeof ( cpu_set_t ), mask ) == -1 ) { 54 | //app_panic("Get cpu affinity failed.\n"); 55 | } 56 | } 57 | 58 | static inline void set_cpu_mask ( pid_t pid, cpu_set_t *mask ) 59 | { 60 | if ( sched_setaffinity ( pid, sizeof ( cpu_set_t ), mask ) == -1 ) { 61 | //app_panic("Set cpu affinity failed.\n"); 62 | } 63 | } 64 | #endif 65 | void active_cpu ( uint32_t active_cpu ) 66 | { 67 | #ifdef linux 68 | cpu_set_t cpu_mask; 69 | int cpu_count = sysconf ( _SC_NPROCESSORS_ONLN ); 70 | 71 | if ( cpu_count < 1 ) { 72 | return; 73 | } 74 | 75 | active_cpu = active_cpu % cpu_count; 76 | 77 | get_cpu_mask ( 0, &cpu_mask ); 78 | //print_cpu_mask(cpu_mask); 79 | 80 | CPU_ZERO ( &cpu_mask ); 81 | CPU_SET ( active_cpu, &cpu_mask ); 82 | set_cpu_mask ( 0, &cpu_mask ); 83 | 84 | //get_cpu_mask(0, &cpu_mask); 85 | //print_cpu_mask(cpu_mask); 86 | #endif 87 | } 88 | 89 | void initproctitle (int argc, char **argv) 90 | { 91 | _argc = argc; 92 | _argv = argv; 93 | int i; 94 | size_t n = 0; 95 | //get process name 96 | #ifdef linux 97 | n = readlink ( "/proc/self/exe" , process_chdir , sizeof ( process_chdir ) ); 98 | #else 99 | uint32_t new_argv0_s = sizeof ( process_chdir ); 100 | 101 | if ( _NSGetExecutablePath ( process_chdir, &new_argv0_s ) == 0 ) { 102 | n = strlen ( process_chdir ); 103 | } 104 | 105 | #endif 106 | i = n; 107 | 108 | while ( n > 1 ) if ( process_chdir[n--] == '/' ) { 109 | strncpy ( process_name, ( ( char * ) process_chdir ) + n + 2, i - n ); 110 | process_chdir[n + 1] = '\0'; 111 | break; 112 | } 113 | 114 | chdir ( process_chdir ); 115 | 116 | n = 0; 117 | 118 | for ( i = 0; argv[i]; ++i ) { 119 | n += strlen ( argv[i] ) + 1; 120 | } 121 | 122 | char *raw = malloc ( n ); 123 | 124 | for ( i = 0; argv[i]; ++i ) { 125 | memcpy ( raw, argv[i], strlen ( argv[i] ) + 1 ); 126 | environ[i] = raw; 127 | raw += strlen ( environ[i] ) + 1; 128 | } 129 | 130 | process_char_last = argv[0]; 131 | 132 | for ( i = 0; i < argc; ++i ) { 133 | process_char_last += strlen ( argv[i] ) + 1; 134 | } 135 | 136 | for ( i = 0; environ[i]; ++i ) { 137 | process_char_last += strlen ( environ[i] ) + 1; 138 | } 139 | 140 | // return process_chdir; 141 | } 142 | 143 | void setProcTitle ( const char *title, int is_master ) 144 | { 145 | _argv[1] = 0; 146 | char *p = _argv[0]; 147 | memset ( p, 0x00, process_char_last - p ); 148 | 149 | if ( is_master ) { 150 | snprintf ( p, process_char_last - p, "%s: %s %s", process_name, title, process_chdir ); 151 | int i = 1; 152 | 153 | for ( i = 1; i < _argc; i++ ) { 154 | sprintf ( p, "%s %s", p, environ[i] ); 155 | } 156 | 157 | } else { 158 | snprintf ( p, process_char_last - p, "%s: %s", process_name, title ); 159 | } 160 | } 161 | 162 | void daemonize() 163 | { 164 | int i, lfp; 165 | char str[10]; 166 | 167 | if ( getppid() == 1 ) { 168 | return; 169 | } 170 | 171 | i = fork(); 172 | 173 | if ( i < 0 ) { 174 | exit ( 1 ); 175 | } 176 | 177 | if ( i > 0 ) { 178 | exit ( 0 ); 179 | } 180 | 181 | setsid(); 182 | signal ( SIGCHLD, SIG_IGN ); 183 | signal ( SIGTSTP, SIG_IGN ); 184 | signal ( SIGTTOU, SIG_IGN ); 185 | signal ( SIGTTIN, SIG_IGN ); 186 | signal ( SIGHUP, signal_handler ); 187 | signal ( SIGTERM, signal_handler ); 188 | } 189 | 190 | void signal_handler ( int sig ) 191 | { 192 | switch ( sig ) { 193 | case SIGHUP: 194 | break; 195 | 196 | case SIGTERM: 197 | _signal_handler = 1; 198 | break; 199 | } 200 | } 201 | static int _workerprocess[200]; 202 | static int _workerprocess_count = 0; 203 | static void ( *_workerprocess_func[200] ) (); 204 | int forkProcess ( void ( *func ) () ) 205 | { 206 | int ret = fork(); 207 | 208 | if ( ret == 0 ) { 209 | active_cpu ( _workerprocess_count ); 210 | func ( _workerprocess_count ); 211 | } 212 | 213 | if ( ret > 0 ) { 214 | _workerprocess[_workerprocess_count] = ret; 215 | _workerprocess_func[_workerprocess_count] = func; 216 | _workerprocess_count++; 217 | } 218 | 219 | return ret; 220 | } 221 | 222 | static void worker_main ( ) 223 | { 224 | 225 | setProcTitle ( "worker process", 0 ); 226 | sleep(10); 227 | exit ( 0 ); 228 | } 229 | int main(int argc, char *argv[]) 230 | { 231 | int i; 232 | initproctitle(argc, argv); 233 | setProcTitle("master process", 1); 234 | daemonize(); 235 | for ( i = 0; i < 5; i++ ) { 236 | forkProcess ( worker_main ); 237 | } 238 | sleep(300); // you can ps now 239 | return 0; 240 | } 241 | -------------------------------------------------------------------------------- /myepoll.c: -------------------------------------------------------------------------------- 1 | /* 2 | * myepoll.cpp 3 | * 4 | * Created on: 2013-06-03 5 | * Author: liuxiaoxian 6 | * To improve the MS concurrency research: sent to the client's data sent over 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "lxx_net.h" 20 | 21 | using namespace std; 22 | #define MAX_EPOLL_SIZE 500 23 | #define MAX_CLIENT_SIZE 500 24 | #define MAX_IP_LEN 16 25 | #define MAX_CLIENT_BUFF_LEN 1024 26 | #define QUEUE_LEN 500 27 | #define BUFF_LEN 1024 28 | int fd_epoll = -1; 29 | int fd_listen = -1; 30 | 31 | // The customer end connection 32 | typedef struct { 33 | int fd; // The connection handle 34 | char host[MAX_IP_LEN]; // IP address 35 | int port; // Port 36 | int len; // Data buffer size 37 | char buff[MAX_CLIENT_BUFF_LEN]; // Buffer data 38 | bool status; // State 39 | } client_t; 40 | 41 | client_t *ptr_cli = NULL; 42 | 43 | // Join epoll 44 | int epoll_add(int fd_epoll, int fd, struct epoll_event *ev) { 45 | if (fd_epoll <0 || fd <0 || ev == NULL) { 46 | return -1; 47 | } 48 | 49 | if (epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd, ev) <0) { 50 | fprintf(stderr, "epoll_add failed(epoll_ctl)[fd_epoll:%d,fd:%d][%s]\n", 51 | fd_epoll, fd, strerror(errno)); 52 | return -1; 53 | } 54 | 55 | fprintf(stdout, "epoll_add success[fd_epoll:%d,fd:%d]\n", fd_epoll, fd); 56 | return 0; 57 | } 58 | 59 | int epoll_del(int fd_epoll, int fd) { 60 | if (fd_epoll <0 || fd <0) { 61 | return -1; 62 | } 63 | 64 | struct epoll_event ev_del; 65 | if (epoll_ctl(fd_epoll, EPOLL_CTL_DEL, fd, &ev_del) <0) { 66 | fprintf(stderr, "epoll_del failed(epoll_ctl)[fd_epoll:%d,fd:%d][%s]\n", 67 | fd_epoll, fd, strerror(errno)); 68 | return -1; 69 | } 70 | close(fd); 71 | fprintf(stdout, "epoll_del success[epoll_fd:%d,fd:%d]\n", fd_epoll, fd); 72 | return 0; 73 | } 74 | 75 | // Receive data 76 | void do_read_data(int idx) { 77 | if (idx >= MAX_CLIENT_SIZE) { 78 | return; 79 | } 80 | int n; 81 | size_t pos = ptr_cli[idx].len; 82 | 83 | if ((n = recv(ptr_cli[idx].fd, ptr_cli[idx].buff+pos, MAX_CLIENT_BUFF_LEN-pos, 0))) { // Buffer data have been received 84 | fprintf(stdout, "[IP:%s,port:%d], data:%s\n", ptr_cli[idx].host, ptr_cli[idx].port, ptr_cli[idx].buff); 85 | send(ptr_cli[idx].fd, ptr_cli[idx].buff, pos+1, 0); 86 | } else if (n > 0) { // Buffer zone and data readability 87 | ptr_cli[idx].len += n; 88 | } else if (errno != EAGAIN) { // To end the connection is closed 89 | fprintf(stdout, "The Client closed(read)[IP:%s,port:%d]\n", ptr_cli[idx].host, ptr_cli[idx].port); 90 | epoll_del(fd_epoll, ptr_cli[idx].fd); 91 | ptr_cli[idx].status = false; 92 | } 93 | } 94 | 95 | // Accept new connections 96 | static void do_accept_client() { 97 | struct epoll_event ev; 98 | struct sockaddr_in cliaddr; 99 | socklen_t cliaddr_len = sizeof(cliaddr); 100 | 101 | int conn_fd = lxx_net_accept(fd_listen, (struct sockaddr *)&cliaddr, &cliaddr_len); 102 | if (conn_fd >= 0) { 103 | if (lxx_net_set_socket(conn_fd, false) != 0) { 104 | close(conn_fd); 105 | fprintf(stderr, "do_accept_client failed(setnonblock)[%s:%d]\n", 106 | inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); 107 | return; 108 | } 109 | 110 | int i = 0; 111 | bool flag = true; 112 | 113 | // Looking for the right. 114 | for (i = 0; i 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define MAXEVENTS 64 14 | 15 | static int 16 | make_socket_non_blocking (int sfd) 17 | { 18 | int flags, s; 19 | 20 | flags = fcntl (sfd, F_GETFL, 0); 21 | if (flags == -1) 22 | { 23 | perror ("fcntl"); 24 | return -1; 25 | } 26 | 27 | flags |= O_NONBLOCK; 28 | s = fcntl (sfd, F_SETFL, flags); 29 | if (s == -1) 30 | { 31 | perror ("fcntl"); 32 | return -1; 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | static int 39 | create_and_bind (char *port) 40 | { 41 | struct addrinfo hints; 42 | struct addrinfo *result, *rp; 43 | int s, sfd; 44 | 45 | memset (&hints, 0, sizeof (struct addrinfo)); 46 | hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ 47 | hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ 48 | hints.ai_flags = AI_PASSIVE; /* All interfaces */ 49 | 50 | s = getaddrinfo (NULL, port, &hints, &result); 51 | if (s != 0) 52 | { 53 | fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s)); 54 | return -1; 55 | } 56 | 57 | for (rp = result; rp != NULL; rp = rp->ai_next) 58 | { 59 | sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); 60 | if (sfd == -1) 61 | continue; 62 | 63 | s = bind (sfd, rp->ai_addr, rp->ai_addrlen); 64 | if (s == 0) 65 | { 66 | /* We managed to bind successfully! */ 67 | break; 68 | } 69 | 70 | close (sfd); 71 | } 72 | 73 | if (rp == NULL) 74 | { 75 | fprintf (stderr, "Could not bind\n"); 76 | return -1; 77 | } 78 | 79 | freeaddrinfo (result); 80 | 81 | return sfd; 82 | } 83 | 84 | int 85 | main (int argc, char *argv[]) 86 | { 87 | int sfd, s; 88 | int efd; 89 | struct epoll_event event; 90 | struct epoll_event *events; 91 | 92 | if (argc != 2) 93 | { 94 | fprintf (stderr, "Usage: %s [port]\n", argv[0]); 95 | exit (EXIT_FAILURE); 96 | } 97 | 98 | sfd = create_and_bind (argv[1]); 99 | if (sfd == -1) 100 | abort (); 101 | 102 | s = make_socket_non_blocking (sfd); 103 | if (s == -1) 104 | abort (); 105 | 106 | s = listen (sfd, SOMAXCONN); 107 | if (s == -1) 108 | { 109 | perror ("listen"); 110 | abort (); 111 | } 112 | 113 | efd = epoll_create1 (0); 114 | if (efd == -1) 115 | { 116 | perror ("epoll_create"); 117 | abort (); 118 | } 119 | 120 | event.data.fd = sfd; 121 | event.events = EPOLLIN | EPOLLET; 122 | s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event); 123 | if (s == -1) 124 | { 125 | perror ("epoll_ctl"); 126 | abort (); 127 | } 128 | 129 | /* Buffer where events are returned */ 130 | events = calloc (MAXEVENTS, sizeof event); 131 | 132 | /* The event loop */ 133 | while (1) 134 | { 135 | int n, i; 136 | 137 | n = epoll_wait (efd, events, MAXEVENTS, -1); 138 | for (i = 0; i < n; i++) 139 | { 140 | if ((events[i].events & EPOLLERR) || 141 | (events[i].events & EPOLLHUP) || 142 | (!(events[i].events & EPOLLIN))) 143 | { 144 | /* An error has occured on this fd, or the socket is not 145 | ready for reading (why were we notified then?) */ 146 | fprintf (stderr, "epoll error\n"); 147 | close (events[i].data.fd); 148 | continue; 149 | } 150 | 151 | else if (sfd == events[i].data.fd) 152 | { 153 | /* We have a notification on the listening socket, which 154 | means one or more incoming connections. */ 155 | while (1) 156 | { 157 | struct sockaddr in_addr; 158 | socklen_t in_len; 159 | int infd; 160 | char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 161 | 162 | in_len = sizeof in_addr; 163 | infd = accept (sfd, &in_addr, &in_len); 164 | if (infd == -1) 165 | { 166 | if ((errno == EAGAIN) || 167 | (errno == EWOULDBLOCK)) 168 | { 169 | /* We have processed all incoming 170 | connections. */ 171 | break; 172 | } 173 | else 174 | { 175 | perror ("accept"); 176 | break; 177 | } 178 | } 179 | 180 | s = getnameinfo (&in_addr, in_len, 181 | hbuf, sizeof hbuf, 182 | sbuf, sizeof sbuf, 183 | NI_NUMERICHOST | NI_NUMERICSERV); 184 | if (s == 0) 185 | { 186 | printf("Accepted connection on descriptor %d " 187 | "(host=%s, port=%s)\n", infd, hbuf, sbuf); 188 | } 189 | 190 | /* Make the incoming socket non-blocking and add it to the 191 | list of fds to monitor. */ 192 | s = make_socket_non_blocking (infd); 193 | if (s == -1) 194 | abort (); 195 | 196 | event.data.fd = infd; 197 | event.events = EPOLLIN | EPOLLET; 198 | s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event); 199 | if (s == -1) 200 | { 201 | perror ("epoll_ctl"); 202 | abort (); 203 | } 204 | } 205 | continue; 206 | } 207 | else 208 | { 209 | /* We have data on the fd waiting to be read. Read and 210 | display it. We must read whatever data is available 211 | completely, as we are running in edge-triggered mode 212 | and won't get a notification again for the same 213 | data. */ 214 | int done = 0; 215 | 216 | while (1) 217 | { 218 | ssize_t count; 219 | char buf[512]; 220 | 221 | count = read (events[i].data.fd, buf, sizeof buf); 222 | if (count == -1) 223 | { 224 | /* If errno == EAGAIN, that means we have read all 225 | data. So go back to the main loop. */ 226 | if (errno != EAGAIN) 227 | { 228 | perror ("read"); 229 | done = 1; 230 | } 231 | break; 232 | } 233 | else if (count == 0) 234 | { 235 | /* End of file. The remote has closed the 236 | connection. */ 237 | done = 1; 238 | break; 239 | } 240 | 241 | /* Write the buffer to standard output */ 242 | s = write (1, buf, count); 243 | if (s == -1) 244 | { 245 | perror ("write"); 246 | abort (); 247 | } 248 | } 249 | 250 | if (done) 251 | { 252 | printf ("Closed connection on descriptor %d\n", 253 | events[i].data.fd); 254 | 255 | /* Closing the descriptor will make epoll remove it 256 | from the set of descriptors which are monitored. */ 257 | close (events[i].data.fd); 258 | } 259 | } 260 | } 261 | } 262 | 263 | free (events); 264 | 265 | close (sfd); 266 | 267 | return EXIT_SUCCESS; 268 | } 269 | 270 | -------------------------------------------------------------------------------- /epoll_server.c: -------------------------------------------------------------------------------- 1 | //https://github.com/hnakamur/luajit-examples/blob/master/socket/c/epoll-server.c 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static int 14 | create_and_bind (char *port) 15 | { 16 | struct addrinfo hints; 17 | struct addrinfo *result, *rp; 18 | int s, sfd; 19 | 20 | memset (&hints, 0, sizeof (struct addrinfo)); 21 | hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ 22 | hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ 23 | hints.ai_flags = AI_PASSIVE; /* All interfaces */ 24 | 25 | s = getaddrinfo (NULL, port, &hints, &result); 26 | if (s != 0) 27 | { 28 | fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s)); 29 | return -1; 30 | } 31 | 32 | for (rp = result; rp != NULL; rp = rp->ai_next) 33 | { 34 | sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); 35 | if (sfd == -1) 36 | continue; 37 | 38 | s = bind (sfd, rp->ai_addr, rp->ai_addrlen); 39 | if (s == 0) 40 | { 41 | /* We managed to bind successfully! */ 42 | break; 43 | } 44 | 45 | close (sfd); 46 | } 47 | 48 | if (rp == NULL) 49 | { 50 | fprintf (stderr, "Could not bind\n"); 51 | return -1; 52 | } 53 | 54 | freeaddrinfo (result); 55 | 56 | return sfd; 57 | } 58 | 59 | static int 60 | make_socket_non_blocking (int sfd) 61 | { 62 | int flags, s; 63 | 64 | flags = fcntl (sfd, F_GETFL, 0); 65 | if (flags == -1) 66 | { 67 | perror ("fcntl"); 68 | return -1; 69 | } 70 | 71 | flags |= O_NONBLOCK; 72 | s = fcntl (sfd, F_SETFL, flags); 73 | if (s == -1) 74 | { 75 | perror ("fcntl"); 76 | return -1; 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | #define MAXEVENTS 64 83 | 84 | static const char reply[] = 85 | "HTTP/1.0 200 OK\r\n" 86 | "Content-type: text/html\r\n" 87 | "Connection: close\r\n" 88 | "Content-Length: 82\r\n" 89 | "\r\n" 90 | "\n" 91 | "\n" 92 | "performance test\n" 93 | "\n" 94 | "\n" 95 | "test\n" 96 | "\n" 97 | "" 98 | ; 99 | 100 | int 101 | main (int argc, char *argv[]) 102 | { 103 | int sfd, s; 104 | int efd; 105 | struct epoll_event event; 106 | struct epoll_event *events; 107 | 108 | if (argc != 2) 109 | { 110 | fprintf (stderr, "Usage: %s [port]\n", argv[0]); 111 | exit (EXIT_FAILURE); 112 | } 113 | 114 | sfd = create_and_bind (argv[1]); 115 | if (sfd == -1) 116 | abort (); 117 | 118 | s = make_socket_non_blocking (sfd); 119 | if (s == -1) 120 | abort (); 121 | 122 | s = listen (sfd, SOMAXCONN); 123 | if (s == -1) 124 | { 125 | perror ("listen"); 126 | abort (); 127 | } 128 | 129 | efd = epoll_create1 (0); 130 | if (efd == -1) 131 | { 132 | perror ("epoll_create"); 133 | abort (); 134 | } 135 | 136 | event.data.fd = sfd; 137 | event.events = EPOLLIN | EPOLLET; 138 | s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event); 139 | if (s == -1) 140 | { 141 | perror ("epoll_ctl"); 142 | abort (); 143 | } 144 | 145 | /* Buffer where events are returned */ 146 | events = calloc (MAXEVENTS, sizeof event); 147 | 148 | /* The event loop */ 149 | while (1) 150 | { 151 | int n, i; 152 | 153 | n = epoll_wait (efd, events, MAXEVENTS, -1); 154 | for (i = 0; i < n; i++) 155 | { 156 | if ((events[i].events & EPOLLERR) || 157 | (events[i].events & EPOLLHUP) || 158 | (!(events[i].events & EPOLLIN))) 159 | { 160 | /* An error has occured on this fd, or the socket is not 161 | * ready for reading (why were we notified then?) */ 162 | fprintf (stderr, "epoll error. events=%u\n", events[i].events); 163 | close (events[i].data.fd); 164 | continue; 165 | } 166 | 167 | else if (sfd == events[i].data.fd) 168 | { 169 | /* We have a notification on the listening socket, which 170 | * means one or more incoming connections. */ 171 | while (1) 172 | { 173 | struct sockaddr in_addr; 174 | socklen_t in_len; 175 | int infd; 176 | #if 0 177 | char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 178 | #endif 179 | 180 | in_len = sizeof in_addr; 181 | infd = accept (sfd, &in_addr, &in_len); 182 | if (infd == -1) 183 | { 184 | printf("errno=%d, EAGAIN=%d, EWOULDBLOCK=%d\n", errno, EAGAIN, EWOULDBLOCK); 185 | if ((errno == EAGAIN) || 186 | (errno == EWOULDBLOCK)) 187 | { 188 | /* We have processed all incoming 189 | * connections. */ 190 | printf ("processed all incoming connections.\n"); 191 | break; 192 | } 193 | else 194 | { 195 | perror ("accept"); 196 | break; 197 | } 198 | } 199 | 200 | #if 0 201 | s = getnameinfo (&in_addr, in_len, 202 | hbuf, sizeof hbuf, 203 | sbuf, sizeof sbuf, 204 | NI_NUMERICHOST | NI_NUMERICSERV); 205 | if (s == 0) 206 | { 207 | printf("Accepted connection on descriptor %d " 208 | "(host=%s, port=%s)\n", infd, hbuf, sbuf); 209 | } 210 | #endif 211 | 212 | /* Make the incoming socket non-blocking and add it to the 213 | * list of fds to monitor. */ 214 | s = make_socket_non_blocking (infd); 215 | if (s == -1) 216 | abort (); 217 | 218 | event.data.fd = infd; 219 | event.events = EPOLLIN | EPOLLET; 220 | printf("set events %u, infd=%d\n", event.events, infd); 221 | s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event); 222 | if (s == -1) 223 | { 224 | perror ("epoll_ctl"); 225 | abort (); 226 | } 227 | } 228 | /* continue; */ 229 | } 230 | else 231 | { 232 | /* We have data on the fd waiting to be read. Read and 233 | * display it. We must read whatever data is available 234 | * completely, as we are running in edge-triggered mode 235 | * and won't get a notification again for the same 236 | * data. */ 237 | int done = 0; 238 | 239 | while (1) 240 | { 241 | ssize_t count; 242 | char buf[512]; 243 | 244 | count = read (events[i].data.fd, buf, sizeof buf); 245 | if (count == -1) 246 | { 247 | /* If errno == EAGAIN, that means we have read all 248 | * data. So go back to the main loop. */ 249 | if (errno != EAGAIN) 250 | { 251 | perror ("read"); 252 | done = 1; 253 | } 254 | break; 255 | } 256 | else if (count == 0) 257 | { 258 | /* End of file. The remote has closed the 259 | * connection. */ 260 | done = 1; 261 | break; 262 | } 263 | 264 | /* Write the reply to connection */ 265 | s = write (events[i].data.fd, reply, sizeof(reply)); 266 | if (s == -1) 267 | { 268 | perror ("write"); 269 | abort (); 270 | } 271 | } 272 | 273 | if (done) 274 | { 275 | printf ("Closed connection on descriptor %d\n", 276 | events[i].data.fd); 277 | 278 | /* Closing the descriptor will make epoll remove it 279 | * from the set of descriptors which are monitored. */ 280 | close (events[i].data.fd); 281 | } 282 | } 283 | } 284 | } 285 | 286 | free (events); 287 | 288 | close (sfd); 289 | 290 | return EXIT_SUCCESS; 291 | } 292 | -------------------------------------------------------------------------------- /epoll_poll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | const int EPOLL_SIZE=5000; 14 | const int EVENT_ARR=5000; 15 | const int PORT=8002; 16 | const int BUF_SIZE=5000; 17 | const int BACK_QUEUE=100; 18 | const int THREAD_MAX=100; 19 | static unsigned int s_thread_para[THREAD_MAX][8]; //线程参数 20 | static pthread_t s_tid[THREAD_MAX]; //线程ID 21 | pthread_mutex_t s_mutex[THREAD_MAX]; //线程锁 22 | int epFd; //epoll 23 | struct epoll_event ev,evs[EVENT_ARR]; 24 | 25 | char *get_type(char *url,char *buf) 26 | { 27 | 28 | const char *t=url+strlen(url); 29 | char type[64]; 30 | for(;t>=url&&*t!='.';--t) ; 31 | 32 | strcpy(type,t+1); 33 | if(strcmp(type,"html")==0||strcmp(type,"htm")==0) 34 | sprintf(buf,"text/%s",type); 35 | else if(strcmp(type,"gif")==0|| 36 | strcmp(type,"jpg")==0|| 37 | strcmp(type,"jpeg")==0|| 38 | strcmp(type,"png")==0) 39 | sprintf(buf,"image/%s",type); 40 | else if(strcmp(type,"/")==0) 41 | sprintf(buf,"text/html"); 42 | else if(strcmp(type,"css")==0) 43 | sprintf(buf,"text/css"); 44 | else if(strcmp(type,"js")==0) 45 | sprintf(buf,"application/x-javascript"); 46 | else 47 | { 48 | 49 | sprintf( buf, "unknown" ); 50 | } 51 | 52 | return buf; 53 | 54 | } 55 | void* http_server(int thread_para[]) 56 | { 57 | int pool_index; //thread pool ID 58 | int clientFd; //client socket 59 | char buf[BUF_SIZE]; 60 | pthread_detach(pthread_self()); 61 | pool_index=thread_para[7]; 62 | 63 | wait_unlock: 64 | pthread_mutex_lock(s_mutex+pool_index); //wait for thread unlock 65 | clientFd=thread_para[1]; //client socket ID 66 | //先进行试探性读取 67 | int len=read(clientFd,buf,BUF_SIZE); 68 | printf("%s",buf); 69 | if(len>0) 70 | { 71 | char *token=strtok(buf," "); //GET 72 | printf("token:%s",token); 73 | char type[64]; 74 | char *url=strtok(NULL," "); //URL 75 | while(*url=='.'||*url=='/')++url; 76 | printf("url:%s",url); 77 | char file[1280000]; 78 | 79 | sprintf(file,"%s",url); 80 | printf("file:%s",file); 81 | 82 | FILE *fp=fopen(file,"rb"); 83 | 84 | if(fp==0) 85 | { 86 | char response[]="HTTP/1.1 404 NOT FOUND\r\n\r\n"; 87 | printf("HTTP/1.1 404 NOT FOUND\r\n\r\n"); 88 | write(clientFd,response,strlen(response)); 89 | } 90 | 91 | else 92 | { 93 | 94 | int file_size; 95 | char *content; 96 | char *response; 97 | fseek(fp,0,SEEK_END); 98 | file_size=ftell(fp); 99 | fseek(fp,0,SEEK_SET); 100 | content=(char *)malloc(file_size+1); 101 | response=(char*)malloc(200); 102 | fread(content,file_size,1,fp); 103 | content[file_size]=0; 104 | sprintf(response,"HTTP/1.1 200 OK\r\nContent-Length:%d\r\nContent-Type:%s\r\n\r\n",file_size,get_type(url,type)); 105 | // printf("HTTP/1.1 200 OK\r\nContent-Type:%s\r\nContent-Length:%d\r\n\r\n%s",get_type(url,type),file_size,content); 106 | write(clientFd,response,strlen(response)); 107 | write(clientFd,content,file_size); 108 | free(content); 109 | free(response); 110 | 111 | } 112 | } 113 | else if(len==0) 114 | { 115 | //触发了EPOLL事件,却没有读取,表示断线 116 | //printf("Client closed at %s\n",inet_ntoa(clientAddr.sin_addr)); 117 | epoll_ctl(epFd,EPOLL_CTL_DEL,clientFd,&ev); 118 | close(clientFd); 119 | int i=thread_para[3]; 120 | evs[i].data.fd=-1; 121 | 122 | } 123 | else if(len==EAGAIN) 124 | { 125 | printf("socket huan cun man le!\n"); 126 | 127 | } 128 | else 129 | { 130 | //client读取出错 131 | printf("Client read failed!\n"); 132 | } 133 | thread_para[0] = 0;//设置线程占用标志为"空闲" 134 | goto wait_unlock; 135 | 136 | printf("pthread exit!\n"); 137 | pthread_exit(NULL); 138 | 139 | } 140 | 141 | static int init_thread_pool(void) 142 | { 143 | int i,rc; 144 | for(i=0;i0) 254 | { 255 | //查询空闲线程对 256 | 257 | for(j = 0; j < THREAD_MAX; j++) { 258 | if (0 == s_thread_para[j][0]) break; 259 | } 260 | if (j >= THREAD_MAX) { 261 | fprintf(stderr, "线程池已满, 连接将被放弃\r\n"); 262 | shutdown(clientFd, SHUT_RDWR); 263 | close(clientFd); 264 | continue; 265 | } 266 | //复制有关参数 267 | s_thread_para[j][0] = 1;//设置活动标志为"活动" 268 | s_thread_para[j][1] = clientFd;//客户端连接 269 | s_thread_para[j][2] = serverFd;//服务索引 270 | s_thread_para[j][3]=i; //epoll event id; 271 | //线程解锁 272 | pthread_mutex_unlock(s_mutex + j); } 273 | else printf("other error!\n"); 274 | } 275 | } 276 | } 277 | return 0; 278 | } 279 | -------------------------------------------------------------------------------- /sockevent.c: -------------------------------------------------------------------------------- 1 | //https://jve.linuxwall.info/ressources/code/sockevent.c 2 | /* sockevent.c 3 | * create TCP socket and store then in a epoll file descriptor 4 | * build with : gcc -O3 -g -falign-functions=4 -falign-jumps -falign-loops -Wall -o sockevent sockevent.c 5 | */ 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | /* catch SIGINT and set stop to signal_id 24 | */ 25 | int stop; 26 | void interrupt(int signal_id) 27 | { 28 | stop = signal_id; 29 | } 30 | 31 | // init struct for statistics 32 | struct statistics 33 | { 34 | int reqsent; 35 | int bytessent; 36 | int reprecv; 37 | int bytesrecv; 38 | int error; 39 | int nbsock; 40 | }; 41 | 42 | void printstats(struct statistics *stats) 43 | { 44 | struct statistics previous; 45 | previous.reqsent = 0; 46 | previous.reprecv = 0; 47 | int banner = 0; 48 | 49 | printf("\nreprecv\tbytes\t^hit\treqsent\tbytes\t^req\tErrors\tActive\n"); 50 | 51 | for(;;) 52 | { 53 | sleep(1); 54 | if(banner == 10) 55 | { 56 | printf("\nreprecv\tbytes\t^hit\treqsent\tbytes\t^req\tErrors\tActive\n"); 57 | banner = 0; 58 | } 59 | else 60 | banner++; 61 | 62 | 63 | printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", stats->reprecv, stats->bytesrecv, stats->reprecv - previous.reprecv,stats->reqsent, stats->bytessent, stats->reqsent - previous.reqsent, stats->error, stats->nbsock); 64 | 65 | previous.reqsent = stats->reqsent; 66 | previous.reprecv = stats->reprecv; 67 | } 68 | 69 | } 70 | 71 | 72 | /* WT (inject29) function to convert a ip:port chain into a sockaddr struct */ 73 | struct sockaddr_in str2sa(char *str) 74 | { 75 | static struct sockaddr_in sa; 76 | char *c; 77 | int port; 78 | 79 | bzero(&sa, sizeof(sa)); 80 | str=strdup(str); 81 | if ((c=strrchr(str,':')) != NULL) { 82 | *c++=0; 83 | port=atol(c); 84 | } 85 | else 86 | port=0; 87 | 88 | if (!inet_aton(str, &sa.sin_addr)) { 89 | struct hostent *he; 90 | 91 | if ((he = gethostbyname(str)) == NULL) 92 | fprintf(stderr,"[NetTools] Invalid server name: %s\n",str); 93 | else 94 | sa.sin_addr = *(struct in_addr *) *(he->h_addr_list); 95 | } 96 | sa.sin_port=htons(port); 97 | sa.sin_family=AF_INET; 98 | 99 | free(str); 100 | return sa; 101 | } 102 | 103 | /* create a TCP socket with non blocking options and connect it to the target 104 | * if succeed, add the socket in the epoll list and exit with 0 105 | */ 106 | int create_and_connect( struct sockaddr_in target , int *epfd) 107 | { 108 | int yes = 1; 109 | int sock; 110 | 111 | // epoll mask that contain the list of epoll events attached to a network socket 112 | static struct epoll_event Edgvent; 113 | 114 | 115 | if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 116 | { 117 | perror("socket"); 118 | exit(1); 119 | } 120 | 121 | // set socket to non blocking and allow port reuse 122 | if ( (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) || 123 | fcntl(sock, F_SETFL, O_NONBLOCK)) == -1) 124 | { 125 | perror("setsockopt || fcntl"); 126 | exit(1); 127 | } 128 | 129 | if( connect(sock, (struct sockaddr *)&target, sizeof(struct sockaddr)) == -1 130 | && errno != EINPROGRESS) 131 | { 132 | // connect doesn't work, are we running out of available ports ? if yes, destruct the socket 133 | if (errno == EAGAIN) 134 | { 135 | perror("connect is EAGAIN"); 136 | close(sock); 137 | exit(1); 138 | } 139 | } 140 | else 141 | { 142 | /* epoll will wake up for the following events : 143 | * 144 | * EPOLLIN : The associated file is available for read(2) operations. 145 | * 146 | * EPOLLOUT : The associated file is available for write(2) operations. 147 | * 148 | * EPOLLRDHUP : Stream socket peer closed connection, or shut down writing 149 | * half of connection. (This flag is especially useful for writing simple 150 | * code to detect peer shutdown when using Edge Triggered monitoring.) 151 | * 152 | * EPOLLERR : Error condition happened on the associated file descriptor. 153 | * epoll_wait(2) will always wait for this event; it is not necessary to set it in events. 154 | */ 155 | Edgvent.events = EPOLLOUT | EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLET ; 156 | //Edgvent.events = EPOLLOUT | EPOLLIN | EPOLLRDHUP | EPOLLERR; 157 | 158 | Edgvent.data.fd = sock; 159 | 160 | // add the socket to the epoll file descriptors 161 | if(epoll_ctl((int)epfd, EPOLL_CTL_ADD, sock, &Edgvent) != 0) 162 | { 163 | perror("epoll_ctl, adding socket\n"); 164 | exit(1); 165 | } 166 | } 167 | 168 | return 0; 169 | } 170 | 171 | 172 | 173 | 174 | /* reading waiting errors on the socket 175 | * return 0 if there's no, 1 otherwise 176 | */ 177 | int socket_check(int fd) 178 | { 179 | int ret; 180 | int code; 181 | socklen_t len = sizeof(int); 182 | 183 | ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &code, &len); 184 | 185 | if ((ret || code)!= 0) 186 | return 1; 187 | 188 | return 0; 189 | } 190 | 191 | 192 | 193 | 194 | int main(int argc, char *argv[]) 195 | { 196 | 197 | if(argc!=3) 198 | { 199 | printf("gatlinject \n"); 200 | exit(1); 201 | } 202 | 203 | struct sockaddr_in target = str2sa((char *) argv[1]); // convert target information 204 | int maxconn = atoi(argv[2]); //number of sockets to connect to the target 205 | 206 | // internal variables definition 207 | int i, count, datacount; 208 | 209 | char message[] = "hello\n\n"; 210 | int messagelength = strlen(message); 211 | 212 | char buffer[1500]; 213 | int buffersize = strlen(buffer); 214 | 215 | struct statistics stats; 216 | memset(&stats,0x0,6 * sizeof(int)); 217 | pthread_t Statsthread; 218 | 219 | 220 | // time 221 | struct timeval start; 222 | struct timeval current; 223 | float elapsedtime; 224 | 225 | // catch SIGINT to exit in a clean way 226 | struct sigaction sa; 227 | memset(&sa, 0, sizeof(struct sigaction *)); 228 | sa.sa_handler = interrupt; 229 | sa.sa_flags = 0; 230 | sigemptyset (&(sa.sa_mask)); 231 | if(sigaction (SIGINT, &sa, NULL)!= 0) 232 | { 233 | perror("sigaction failed"); 234 | exit(1); 235 | } 236 | 237 | // the epoll file descriptor 238 | int epfd; 239 | 240 | // epoll structure that will contain the current network socket and event when epoll wakes up 241 | static struct epoll_event *events; 242 | static struct epoll_event event_mask; 243 | 244 | // create the special epoll file descriptor 245 | epfd = epoll_create(maxconn); 246 | 247 | // allocate enough memory to store all the events in the "events" structure 248 | if (NULL == (events = calloc(maxconn, sizeof(struct epoll_event)))) 249 | { 250 | perror("calloc events"); 251 | exit(1); 252 | }; 253 | 254 | // create and connect as much as needed 255 | for(i=0;i 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define MAX_LINE 1024 19 | 20 | 21 | 22 | static struct config { 23 | char *path; 24 | char *file; 25 | int port; 26 | int threads; 27 | bool dynamic; 28 | } cfg; 29 | 30 | typedef struct event_ptr { 31 | int fd; 32 | int rein; 33 | char addr[16]; 34 | }event_ptr; 35 | 36 | static void usage() { 37 | printf("Usage: httpv \n" 38 | " Options: \n" 39 | " -p, --path

path of url \n" 40 | " -P, --port

port of host \n" 41 | " -t, --threads Number of threads to use \n" 42 | " \n" 43 | " -f, --file Load ip file \n" 44 | " -H, --header Add header to request \n" 45 | " --latency Print latency statistics \n" 46 | " --timeout Socket/request timeout \n" 47 | " -v, --version Print version details \n" 48 | " \n" 49 | " Numeric arguments may include a SI unit (1k, 1M, 1G)\n" 50 | " Time arguments may include a time unit (2s, 2m, 2h)\n"); 51 | } 52 | 53 | static int parse_args(struct config *cfg, char **headers, int argc, char* argv[]) 54 | { 55 | char **header = headers; 56 | int c; 57 | memset(cfg, 0, sizeof(struct config)); 58 | cfg->path = "/"; 59 | cfg->port = 80; 60 | cfg->file = NULL; 61 | cfg->dynamic = false; 62 | cfg->threads = 1000; 63 | 64 | while ((c = getopt(argc, argv, "f:P:p:t:H:d:h?")) != -1) { 65 | switch (c) { 66 | case 'f': 67 | cfg->file = optarg; 68 | break; 69 | case 'P': cfg->port = atoi(optarg); break; 70 | case 't': cfg->threads = atoi(optarg); break; 71 | case 'p': cfg->path = optarg; break; 72 | case 'H': 73 | *header++ = optarg; 74 | break; 75 | case 'h': 76 | case '?': 77 | default: 78 | return -1; 79 | } 80 | } 81 | *header = NULL; 82 | return 0; 83 | } 84 | 85 | static int create_and_connect( char *host , int *epfd) 86 | { 87 | struct hostent *hp; 88 | struct sockaddr_in addr; 89 | 90 | // epoll mask that contain the list of epoll events attached to a network socket 91 | static struct epoll_event event; 92 | 93 | int sock; 94 | int on = 1; 95 | 96 | if((hp = gethostbyname(host)) == NULL) { 97 | fprintf(stderr,"[NetTools] Invalid server name: %s\n", host); 98 | return -1; 99 | } 100 | bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); 101 | addr.sin_port = htons(cfg.port); 102 | addr.sin_family = AF_INET; 103 | sock = socket(AF_INET, SOCK_STREAM, 0); 104 | // set socket to non blocking and allow port reuse 105 | if ( (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int)) || 106 | fcntl(sock, F_SETFL, O_NONBLOCK)) == -1) 107 | { 108 | perror("setsockopt || fcntl"); 109 | exit(1); 110 | } 111 | if( connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1 112 | && errno != EINPROGRESS) 113 | { 114 | // connect doesn't work, are we running out of available ports ? if yes, destruct the socket 115 | if (errno == EAGAIN || errno == EWOULDBLOCK) 116 | { 117 | perror("connect is EAGAIN"); 118 | //close(sock); 119 | exit(1); 120 | } 121 | } 122 | else 123 | { 124 | /* epoll will wake up for the following events : 125 | * 126 | * EPOLLIN : The associated file is available for read(2) operations. 127 | * 128 | * EPOLLOUT : The associated file is available for write(2) operations. 129 | * 130 | * EPOLLRDHUP : Stream socket peer closed connection, or shut down writing 131 | * half of connection. (This flag is especially useful for writing simple 132 | * code to detect peer shutdown when using Edge Triggered monitoring.) 133 | * 134 | * EPOLLERR : Error condition happened on the associated file descriptor. 135 | * epoll_wait(2) will always wait for this event; it is not necessary to set it in events. 136 | */ 137 | event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLERR | EPOLLET; 138 | //Edgvent.events = EPOLLOUT | EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLET; 139 | 140 | event.data.ptr = malloc(sizeof(event_ptr)); 141 | 142 | struct event_ptr *ptr = event.data.ptr; 143 | bzero(ptr, sizeof(event_ptr)); 144 | ptr->fd = sock; 145 | ptr->rein = 0; 146 | strcpy(ptr->addr, host); 147 | //ptr->addr[strlen(host)] = '\0'; 148 | 149 | // add the socket to the epoll file descriptors 150 | if(epoll_ctl((int)*epfd, EPOLL_CTL_ADD, sock, &event) != 0) 151 | { 152 | perror("epoll_ctl, adding socket\n"); 153 | exit(1); 154 | } 155 | } 156 | 157 | return 0; 158 | } 159 | 160 | /* reading waiting errors on the socket 161 | * return 0 if there's no, 1 otherwise 162 | */ 163 | int socket_check(int fd) 164 | { 165 | int ret; 166 | int code; 167 | int len = sizeof(int); 168 | 169 | ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &code, &len); 170 | 171 | if ((ret || code)!= 0) 172 | return 1; 173 | 174 | return 0; 175 | } 176 | 177 | void stringlink(char *s, char *t) 178 | { 179 | while (*s != '\0') 180 | { 181 | s++; 182 | } 183 | while (*t != '\0') 184 | { 185 | *s++ = *t++; 186 | } 187 | *s = '\0'; 188 | } 189 | 190 | char* substring(const char* str, size_t begin, size_t len) 191 | { 192 | if (str == 0 || strlen(str) == 0 || strlen(str) < begin || strlen(str) < (begin+len)) 193 | return 0; 194 | 195 | return strndup(str + begin, len); 196 | } 197 | 198 | char *substr(char *haystack, char *begin, char *end) 199 | { 200 | char *ret, *r; 201 | char *b = strstr(haystack, begin); 202 | if (b) { 203 | char *e = strstr(b, end); 204 | if(e) { 205 | int offset = e - b; 206 | int retlen = offset - strlen(begin); 207 | if ((ret = malloc(retlen + 1)) == NULL) 208 | return NULL; 209 | strncpy(ret, b + strlen(begin), retlen); 210 | return ret; 211 | } 212 | } 213 | return NULL; 214 | } 215 | 216 | void main(int argc, char* argv[]) 217 | { 218 | char *url, **headers; 219 | headers = malloc((argc / 2) * sizeof(char *)); 220 | 221 | if (parse_args(&cfg, headers, argc, argv)) { 222 | usage(); 223 | exit(1); 224 | } 225 | 226 | char **h; 227 | char header_name[32]; 228 | char header_value[200]; 229 | char header[1024]; 230 | char header_tmp[232]; 231 | event_ptr * ptr; 232 | 233 | if (cfg.file) { 234 | FILE *fp; 235 | char buf[MAX_LINE]; /*缓冲区*/ 236 | int n, len ; 237 | fp = fopen(cfg.file, "r"); 238 | if (fp == NULL) { 239 | printf("file not exist :%s\n", cfg.file); 240 | exit(1); 241 | } 242 | n = 0; 243 | int epfd; 244 | static struct epoll_event *events; 245 | 246 | // create the special epoll file descriptor 247 | epfd = epoll_create(cfg.threads); 248 | 249 | // allocate enough memory to store all the events in the "events" structure 250 | if (NULL == (events = calloc(cfg.threads, sizeof(struct epoll_event)))) 251 | { 252 | perror("calloc events"); 253 | exit(1); 254 | }; 255 | int rn = 0; 256 | master_worker: 257 | while(fgets(buf, MAX_LINE, fp) != NULL) { 258 | len = strlen(buf); 259 | buf[len-1] = '\0'; /* 去掉换行符 */ 260 | if(strlen(buf) >= 7 && create_and_connect(buf, &epfd) != 0) 261 | { 262 | fprintf (stderr, "create and connect : %s\n", buf); 263 | } 264 | ++n; 265 | ++rn; 266 | if(rn > cfg.threads) goto epoll_worker; 267 | } 268 | if (rn == 0) exit(0); 269 | 270 | 271 | epoll_worker: 272 | 273 | sprintf(header, "GET %s HTTP/1.1\r\n", cfg.path); 274 | rn = 0; 275 | for (h = headers; *h; h++) { 276 | char *p = strchr(*h, ':'); 277 | if (p && p[1] == ' ') { 278 | bzero(header_name, 32); 279 | bzero(header_value, 200); 280 | bzero(header_tmp, 232); 281 | strncpy(header_name, *h, strlen(*h) - strlen(p)); 282 | strcpy(header_value, p + 2); 283 | sprintf(header_tmp, "%s: %s\r\n", header_name, header_value); 284 | stringlink(header, header_tmp); 285 | //printf("p=%p(%d), %s => %s\n", p, strlen(p), header_name, header_value); 286 | } 287 | } 288 | stringlink(header, "\r\n"); 289 | int header_len = strlen(header); 290 | char *hhh = malloc( header_len * sizeof(char) + 1); 291 | strcpy(hhh, header); 292 | 293 | printf("%s", hhh); 294 | 295 | char buffer[2049]; 296 | int buffersize = 2048; 297 | int count, i, datacount; 298 | int http_status; 299 | char *http_servername = NULL; 300 | char *http_title = NULL; 301 | while(1) { 302 | count = epoll_wait(epfd, events, cfg.threads, 500); 303 | if(count == 0) break; 304 | for(i=0;ifd, ptr->addr, events[i].events); 307 | if ((events[i].events & (EPOLLHUP | EPOLLERR)) || strlen(ptr->addr) == 0) 308 | { 309 | 310 | epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL); 311 | 312 | //fprintf (stderr, "epoll error %d\n", ptr->fd); 313 | continue; 314 | } 315 | if (events[i].events & EPOLLOUT) //socket is ready for writing 316 | { 317 | // verify the socket is connected and doesn't return an error 318 | if(socket_check(ptr->fd) != 0) 319 | { 320 | perror("write socket_check"); 321 | continue; 322 | } 323 | else 324 | { 325 | 326 | int total = header_len; 327 | while(1) { 328 | datacount = send(ptr->fd, hhh, header_len, 0); 329 | if(datacount < 0) { 330 | if (errno == EINTR || errno == EAGAIN) { 331 | usleep(1000); 332 | continue; 333 | } 334 | } 335 | if (datacount == total) { 336 | events[i].events = EPOLLIN | EPOLLHUP | EPOLLERR; 337 | 338 | if(epoll_ctl(epfd, EPOLL_CTL_MOD, ptr->fd, events) != 0) 339 | { 340 | perror("epoll_ctl, modify socket"); 341 | continue; 342 | } 343 | break; 344 | } 345 | total -= datacount; 346 | hhh += datacount; 347 | } 348 | 349 | } 350 | } 351 | 352 | if (events[i].events & (EPOLLIN )) //socket is ready for reading 353 | { 354 | // verify the socket is connected and doesn't return an error 355 | if(socket_check(ptr->fd) != 0) 356 | { 357 | fprintf (stderr, " [ %s->%d] read socket_check : [%d]%s\n", ptr->addr, ptr->fd, errno, strerror(errno)); 358 | //epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL); 359 | continue; 360 | 361 | } 362 | else 363 | { 364 | memset(buffer,0x0,buffersize); 365 | 366 | int n = 0; 367 | while (1) { 368 | datacount = read(ptr->fd, buffer +n , buffersize); 369 | if(datacount == -1) { 370 | ++ptr->rein; 371 | if (ptr->rein > 5) { 372 | epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL); 373 | break; 374 | } 375 | if (errno == EAGAIN) { 376 | usleep(1000); 377 | continue; 378 | } 379 | 380 | 381 | }else if(datacount == 0) { 382 | break; 383 | } 384 | //printf("%s=%d=%d\n", buffer, n, datacount); 385 | 386 | n += datacount; 387 | } 388 | 389 | 390 | /* 391 | if((datacount = recv(ptr->fd, buffer, buffersize, 0)) < 0 ) 392 | { 393 | ++ptr->rein; 394 | fprintf (stderr, "[ %s->%d] recv failed : %s\n", ptr->addr, ptr->fd, strerror(errno)); 395 | if(ptr->rein > 5) { 396 | epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL); 397 | } 398 | continue; 399 | } 400 | */ 401 | printf("%s\n", buffer); 402 | char *http_status = substring(buffer, 9, 3); 403 | http_servername = substr(buffer, "Server: ", "\r\n"); 404 | http_title = substr(buffer, "", ""); 405 | fprintf (stdout, "%s\t%s\t%s\t%s\n", ptr->addr, http_status, http_servername, http_title); 406 | if(http_status != NULL) free(http_status); 407 | if(http_servername != NULL) free(http_servername); 408 | if(http_title != NULL) free(http_title); 409 | 410 | epoll_ctl(epfd, EPOLL_CTL_DEL, ptr->fd, NULL); 411 | //usleep(10000); 412 | } 413 | } 414 | 415 | } 416 | } 417 | goto master_worker; 418 | } 419 | 420 | //printf("headers: %s\npath: %s\nport: %d\n", *headers, cfg.path, cfg.port); 421 | } 422 | -------------------------------------------------------------------------------- /t2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define MAX_LINE 1024 15 | #ifndef EPOLLRDHUP 16 | #define EPOLLRDHUP 0x2000 17 | #endif 18 | 19 | #ifdef DEBUG 20 | 21 | void * 22 | debug_malloc(size_t size, const char *file, int line, const char *func) 23 | { 24 | void *p; 25 | 26 | p = malloc(size); 27 | printf("%s:%d:%s:malloc(%ld): p=0x%lx\n", 28 | file, line, func, size, (unsigned long)p); 29 | return p; 30 | } 31 | 32 | #define malloc(s) debug_malloc(s, __FILE__, __LINE__, __func__) 33 | #define free(p) do { \ 34 | printf("%s:%d:%s:free(0x%lx)\n", __FILE__, __LINE__, \ 35 | __func__, (unsigned long)p); \ 36 | free(p); \ 37 | } while (0) 38 | 39 | #endif 40 | static struct config { 41 | char *body; 42 | char *file; 43 | char *servername; 44 | char *title; 45 | int port; 46 | int threads; 47 | bool dynamic; 48 | } cfg; 49 | 50 | typedef struct se_ptr_s se_ptr_t; 51 | typedef int (*se_rw_proc_t)(se_ptr_t *ptr); 52 | 53 | struct se_ptr_s { 54 | int loop_fd; 55 | int fd; 56 | se_rw_proc_t rfunc; 57 | se_rw_proc_t wfunc; 58 | char addr[16]; 59 | }; 60 | 61 | static struct epoll_event events[4096], ev; 62 | 63 | 64 | static void usage() { 65 | printf("Usage: httpv \n" 66 | " Options: \n" 67 | " -b, --body data for socket, default <'GET / HTTP/1.1\\r\\nHost: localhost\\r\\n\\r\\n'> \n" 68 | " -P, --port

port of host \n" 69 | " -t, --threads Number of threads to use \n" 70 | " -f, --file Load ip file \n" 71 | " -0, --title match title \n" 72 | " -1, --servername match server \n" 73 | " \n"); 74 | } 75 | static int parse_args(struct config *cfg, int argc, char* argv[]) 76 | { 77 | int c; 78 | memset(cfg, 0, sizeof(struct config)); 79 | cfg->body = "GET / HTTP/1.1\r\nAccept-Encoding: deflate\r\nHost: www.baidu.com\r\n\r\n"; 80 | cfg->port = 80; 81 | cfg->file = NULL; 82 | cfg->dynamic = false; 83 | cfg->threads = 1000; 84 | cfg->servername = NULL; 85 | cfg->title = NULL; 86 | 87 | while ((c = getopt(argc, argv, "0:1:f:P:b:t:d:h?")) != -1) { 88 | switch (c) { 89 | case 'f': 90 | cfg->file = optarg; 91 | break; 92 | case 'P': cfg->port = atoi(optarg); break; 93 | case 't': cfg->threads = atoi(optarg); break; 94 | case 'b': cfg->body = optarg; break; 95 | case '0': cfg->title = optarg; break; 96 | case '1': cfg->servername = optarg; break; 97 | case 'h': 98 | case '?': 99 | default: 100 | return -1; 101 | } 102 | } 103 | return 0; 104 | } 105 | 106 | char* substring(const char* str, size_t begin, size_t len) 107 | { 108 | if (str == 0 || strlen(str) == 0 || strlen(str) < begin || strlen(str) < (begin+len)) 109 | return 0; 110 | 111 | return strndup(str + begin, len); 112 | } 113 | 114 | char *substr(char *haystack, char *begin, char *end) 115 | { 116 | char *ret, *r; 117 | char *b = strstr(haystack, begin); 118 | if (b) { 119 | char *e = strstr(b, end); 120 | if(e) { 121 | int offset = e - b; 122 | int retlen = offset - strlen(begin); 123 | if ((ret = malloc(retlen + 1)) == NULL) 124 | return NULL; 125 | ret[retlen] = '\0'; 126 | strncpy(ret, b + strlen(begin), retlen); 127 | return ret; 128 | } 129 | } 130 | return NULL; 131 | } 132 | 133 | bool setnonblocking(int sockfd) { 134 | int opts; 135 | 136 | opts = fcntl(sockfd, F_GETFL); 137 | if(opts < 0) { 138 | perror("fcntl(F_GETFL)\n"); 139 | return false; 140 | } 141 | opts = (opts | O_NONBLOCK); 142 | if(fcntl(sockfd, F_SETFL, opts) < 0) { 143 | perror("fcntl(F_SETFL)\n"); 144 | return false; 145 | } 146 | return true; 147 | } 148 | 149 | static int connected( char *host) 150 | { 151 | struct hostent *hp; 152 | struct sockaddr_in addr; 153 | 154 | // epoll mask that contain the list of epoll events attached to a network socket 155 | static struct epoll_event event; 156 | 157 | int sock; 158 | int on = 1; 159 | 160 | if((hp = gethostbyname(host)) == NULL) { 161 | fprintf(stderr,"[NetTools] Invalid server name: %s\n", host); 162 | return -1; 163 | } 164 | memset(&addr, 0, sizeof (addr)); 165 | bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); 166 | addr.sin_port = htons(cfg.port); 167 | addr.sin_family = AF_INET; 168 | sock = socket(AF_INET, SOCK_STREAM, 0); 169 | if (sock < 0) 170 | { 171 | fprintf(stderr, "create socket fail"); 172 | return -5; 173 | } 174 | // set socket to non blocking and allow port reuse 175 | if ( (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int)) || 176 | !setnonblocking(sock))) 177 | { 178 | fprintf(stderr, "setsockopt || fcntl"); 179 | return -2; 180 | } 181 | int res = connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)); 182 | 183 | if (res < 0) { 184 | if (errno == EINPROGRESS) { 185 | return sock; 186 | } 187 | close(sock); 188 | return -3; 189 | } 190 | return sock; 191 | } 192 | 193 | int socket_check(int fd) 194 | { 195 | int ret; 196 | int code; 197 | int len = sizeof(int); 198 | 199 | ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &code, &len); 200 | 201 | if ((ret || code)!= 0) 202 | return 1; 203 | 204 | return 0; 205 | } 206 | int se_create(int event_size) 207 | { 208 | return epoll_create(event_size); 209 | } 210 | 211 | se_ptr_t *se_add(int loop_fd, int fd) 212 | { 213 | se_ptr_t *ptr = malloc(sizeof(se_ptr_t)); 214 | 215 | if(!ptr) { 216 | return ptr; 217 | } 218 | 219 | ptr->loop_fd = loop_fd; 220 | ptr->fd = fd; 221 | 222 | ev.data.ptr = ptr; 223 | ev.events = EPOLLPRI; 224 | 225 | int ret = epoll_ctl(loop_fd, EPOLL_CTL_ADD, fd, &ev); 226 | 227 | if(ret < 0) { 228 | free(ptr); 229 | ptr = NULL; 230 | } 231 | return ptr; 232 | } 233 | 234 | int se_delete(se_ptr_t *ptr) 235 | { 236 | if(!ptr) { 237 | return -1; 238 | } 239 | 240 | if(epoll_ctl(ptr->loop_fd, EPOLL_CTL_DEL, ptr->fd, &ev) < 0) { 241 | return -1; 242 | } 243 | 244 | free(ptr); 245 | 246 | return 0; 247 | } 248 | 249 | int se_loop(int loop_fd, int waitout) 250 | { 251 | int n = 0, i = 0; 252 | se_ptr_t *ptr = NULL; 253 | 254 | while(1) { 255 | 256 | n = epoll_wait(loop_fd, events, 4096, waitout); 257 | if(n == 0) break; 258 | for(i = 0; i < n; i++) { 259 | ptr = events[i].data.ptr; 260 | 261 | if (events[i].events & ( EPOLLHUP | EPOLLERR)) 262 | { 263 | se_delete(ptr); 264 | } else if(events[i].events & (EPOLLIN) && ptr->rfunc) { 265 | //printf("rfunc\n"); 266 | ptr->rfunc(ptr); 267 | 268 | } else if(events[i].events & (EPOLLOUT) && ptr->wfunc) { 269 | //printf("wfunc\n"); 270 | ptr->wfunc(ptr); 271 | } 272 | } 273 | 274 | if(n == -1 && errno != EINTR) { 275 | printf("exit\n"); 276 | break; 277 | } 278 | } 279 | 280 | return 0; 281 | } 282 | 283 | int se_be_read(se_ptr_t *ptr, se_rw_proc_t func) 284 | { 285 | ptr->rfunc = func; 286 | ptr->wfunc = NULL; 287 | 288 | ev.data.ptr = ptr; 289 | ev.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLONESHOT; 290 | 291 | return epoll_ctl(ptr->loop_fd, EPOLL_CTL_MOD, ptr->fd, &ev); 292 | } 293 | 294 | int se_be_write(se_ptr_t *ptr, se_rw_proc_t func) 295 | { 296 | ptr->rfunc = NULL; 297 | ptr->wfunc = func; 298 | 299 | ev.data.ptr = ptr; 300 | ev.events = EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLERR | EPOLLET; 301 | 302 | return epoll_ctl(ptr->loop_fd, EPOLL_CTL_MOD, ptr->fd, &ev); 303 | } 304 | 305 | int se_be_pri(se_ptr_t *ptr, se_rw_proc_t func) 306 | { 307 | ptr->rfunc = func; 308 | ptr->wfunc = NULL; 309 | 310 | ev.data.ptr = ptr; 311 | ev.events = EPOLLPRI; 312 | 313 | return epoll_ctl(ptr->loop_fd, EPOLL_CTL_MOD, ptr->fd, &ev); 314 | } 315 | 316 | int se_be_rw(se_ptr_t *ptr, se_rw_proc_t rfunc, se_rw_proc_t wfunc) 317 | { 318 | ptr->rfunc = rfunc; 319 | ptr->wfunc = wfunc; 320 | 321 | ev.data.ptr = ptr; 322 | ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLHUP | EPOLLERR; 323 | 324 | return epoll_ctl(ptr->loop_fd, EPOLL_CTL_MOD, ptr->fd, &ev); 325 | } 326 | 327 | int network_be_read(se_ptr_t *ptr) 328 | { 329 | char *response = NULL; 330 | char buffer[1500]; 331 | int read_size , total_size = 0; 332 | if (socket_check(ptr->fd) == 1) 333 | { 334 | fprintf (stderr, " [ %s->%d] read socket_check : [%d]%s\n", ptr->addr, ptr->fd, errno, strerror(errno)); 335 | //se_be_read(ptr, network_be_read); 336 | return 1; 337 | } 338 | bzero(buffer, 1500); 339 | while( (read_size = recv(ptr->fd , buffer , sizeof(buffer) , 0) )) 340 | { 341 | if((errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)) { 342 | fprintf (stderr, " recv[%d] : [%d]%s\n",read_size, errno, strerror(errno)); 343 | continue; 344 | } 345 | response = realloc(response , read_size + total_size); 346 | if(response == NULL) 347 | { 348 | printf("realloc failed"); 349 | exit(1); 350 | } 351 | memcpy((response + total_size) , buffer , read_size); 352 | total_size += read_size; 353 | } 354 | response = realloc(response , total_size + 1); 355 | *(response + total_size) = '\0'; 356 | if(total_size > 0) { 357 | int m0 = 0; 358 | int m1 = 0; 359 | //printf("read %d=%d: %s\n", n, nread, buffer); 360 | char *http_status = substring(buffer, 9, 3); 361 | char *http_servername = substr(buffer, "Server: ", "\r\n"); 362 | char *http_title = substr(buffer, "", ""); 363 | if (cfg.title != NULL) { 364 | ++m0; 365 | if (http_title != NULL && strstr(http_title, cfg.title) != NULL)++m1; 366 | } 367 | if (cfg.servername != NULL) { 368 | ++m0; 369 | if (http_servername != NULL && strstr(http_servername, cfg.servername) != NULL)++m1; 370 | } 371 | 372 | if( m0 == m1)fprintf(stdout, "%s\t%s\t%s\t%s\n", ptr->addr, http_status, http_servername, http_title); 373 | if(http_status != NULL) free(http_status); 374 | if(http_servername != NULL) free(http_servername); 375 | if(http_title != NULL) free(http_title); 376 | } 377 | if(response != NULL) free(response); 378 | close(ptr->fd); 379 | se_delete(ptr); 380 | return total_size; 381 | 382 | } 383 | int network_be_write(se_ptr_t *ptr) 384 | { 385 | int rs; 386 | 387 | if (socket_check(ptr->fd) == 1) 388 | { 389 | fprintf (stderr, " [ %s->%d] write socket_check : [%d]%s\n", ptr->addr, ptr->fd, errno, strerror(errno)); 390 | se_delete(ptr); 391 | //se_be_write(ptr, network_be_write); 392 | return 1; 393 | } 394 | rs = send(ptr->fd, cfg.body, strlen(cfg.body), 0); 395 | if (rs < 0) { 396 | printf("send error [%d]%s\n", errno, strerror(errno)); 397 | se_delete(ptr); 398 | return 1; 399 | } 400 | se_be_read(ptr, network_be_read); 401 | 402 | } 403 | void main(int argc, char* argv[]) 404 | { 405 | int epfd; 406 | signal(SIGPIPE, SIG_IGN); //oops strace 407 | if (parse_args(&cfg, argc, argv)) { 408 | usage(); 409 | exit(1); 410 | } 411 | if (cfg.file) { 412 | FILE *fp; 413 | char buf[MAX_LINE]; 414 | int n, len ; 415 | fp = fopen(cfg.file, "r"); 416 | if (fp == NULL) { 417 | printf("file not exist :%s\n", cfg.file); 418 | exit(1); 419 | } 420 | n = 0; 421 | epfd = se_create(1024); 422 | int rn = 0; 423 | master_worker: 424 | while(fgets(buf, MAX_LINE, fp) != NULL) { 425 | len = strlen(buf); 426 | buf[len-1] = '\0'; 427 | if(strlen(buf) >= 7) 428 | { 429 | int sockfd = connected(buf); 430 | if (sockfd > 0) 431 | { 432 | se_ptr_t *ptr = se_add(epfd, sockfd); 433 | strcpy(ptr->addr, buf); 434 | se_be_write(ptr, network_be_write); 435 | } 436 | //fprintf (stderr, "create and connect : %s=%d\n", buf, sockfd); 437 | } 438 | ++n; 439 | ++rn; 440 | if(rn > cfg.threads) goto epoll_worker; 441 | } 442 | if (rn == 0) exit(0); 443 | epoll_worker: 444 | fprintf (stderr, "work line: %d - %d\n", (n-cfg.threads) < 0 ? 1 : (n-cfg.threads), n); 445 | rn = 0; 446 | se_loop(epfd, 4000); 447 | goto master_worker; 448 | } 449 | fprintf (stderr, "work done\n"); 450 | } 451 | --------------------------------------------------------------------------------