You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
1.7 KiB

package main
import (
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"runtime"
"sort"
"sync"
)
const max = 1000
type pair struct {
u string
s int64
}
type pairs []pair
func (p pairs) Len() int { return len(p) }
func (p pairs) Swap(a, b int) { p[a], p[b] = p[b], p[a] }
func (p pairs) Less(a, b int) bool { return p[a].s < p[b].s }
var workers = flag.Int("workers", runtime.NumCPU()*4, "number of downloaders")
func main() {
flag.Parse()
for r := range srt(attack(urls(max), *workers)) {
fmt.Printf("%v\t%v\n", r.s, r.u)
}
}
func urls(max int) chan string {
r := make(chan string)
go func() {
for i := 0; i < max; i++ {
r <- fmt.Sprintf("https://hmm.clstr.co/size/%03d", i)
}
close(r)
}()
return r
}
func attack(urls chan string, workers int) chan pair {
r := make(chan pair)
go func() {
c := http.Client{}
s := make(chan bool, workers)
wg := sync.WaitGroup{}
for u := range urls {
wg.Add(1)
s <- true
go func(url string) {
resp, err := c.Get(url)
if err != nil {
log.Printf("probalo: %v", err)
return
}
r <- pair{url, resp.ContentLength}
if n, err := io.Copy(ioutil.Discard, resp.Body); err != nil {
log.Printf("after %v bytes: %v", n, err)
}
if err := resp.Body.Close(); err != nil {
log.Printf("close body: %v", err)
}
<-s
wg.Done()
}(u)
}
wg.Wait()
close(r)
}()
return r
}
func srt(in chan pair) chan pair {
r := make(chan pair)
go func() {
ps := pairs{}
for r := range in {
ps = append(ps, r)
}
sort.Sort(ps)
for _, p := range ps {
r <- p
}
close(r)
}()
return r
}
func print() {
for i := 0; i < 1000; i++ {
fmt.Sprintf("hmm.clstr.co/size/%03d", i)
}
}