#Only one usage of each socket address (protocol/network address/port) is normally permitted
108 messages · Page 1 of 1 (latest)
which error?
Only one usage of each socket address (protocol/network address/port) is normally permitted
I've been on this for days now, and cannot find the solution to it
what prints it? which function errors and return this as err ?
I'm just seeing "Failed to solve captcha", and thats about it.
As said it works fine for the first 15000 solves, then it stops.
probably you’re leaking connections
Also tried with fastHTTP, still the same issue
Myself, and an GoLang developer I hired to investigate looked into it, and neither of us can find the meaning of the issue.
I have looked everywhere for it aswell
Here it stops
that's a different error... a timeout
You've sort of posted three different errors now ("only one usage of each socket address", "failed to solve captcha" and a timeout)
Yes, but the failed to solve cap issue never appears until the issue arrives.
The timeout is nothing, ignore that.
who/what prints "failed to solve" as it's not in the txt you provided
Figuring out what function is returning each error would help with figuring out what's going on. Though "failure to solve" sounds like it's coming from the API, with them saying "whoops, oh well, we can't do it with this one"
That "only one usage" one seems to be Windows-specific and sounds like it could be due to a connection leak, as Moorea said.
func SolveCaptcha() (string, error) {
apikey := captcha_api_key
api := nextcaptcha.NewNextCaptchaAPI(apikey, "0", "https://github.com/", false)
result, err := api.RecaptchaV2Enterprise("https://xxx/", "xxx", nextcaptcha.RecaptchaV2EnterpriseOptions{})
if err != nil {
ui.PrintData(fmt.Sprint(err))
return "", err
}
if result["solution"] == nil {
return "", errors.New("Failed to solve cap!")
}
//ui.PrintData(fmt.Sprint(result["solution"].(map[string]interface{})["gRecaptchaResponse"].(string)))
return result["solution"].(map[string]interface{})["gRecaptchaResponse"].(string), nil
}```
That's this part
If solution is empty, it prints that error.
instead of
if result["solution"] == nil {
return "", errors.New("Failed to solve cap!")
}
you should dump the full reply
But it still does not explain the socket issue
Which is causing this entire pool of errors
which happens first? and which lines prints it? consider using a logger that prints file+line
Well. Uhh. Maybe the API response has more information if solution is missing? So, as Moorea said, dump the whole thing.
I can't seem to find public documentation on the API though.
I suppose the empty solution happends first, I will print it in a second.
It's just pain that I have to spend $15 every time I want to debug this issue
Check netstat -a after like 1000 connections and see if it has a ton of open net connections, maybe.
maybe TIME_WAIT* but from the sent code cursory, it does use a single shared http client so ... it should be doing connection reuse
Windows does only have somewhere around 15k ports in the ephemeral port range, so, a connection leak sounds very likely.
unless you are making many api object
and/or go routines
make sure you're calling NewApiClient only exactly once
I am doing several reqs besides this one, but it seems only this one is reacting to that error
It works fine with lower threads somehow
well... there you go
It could just be that whatever is eating up connections is doing it more slowly on a lower thread count. Lowering the amount of threads to anything but 1 doesn't tend to really mitigate issues.
And you should still check netstat -a to see if you're leaking connections. Having 5k connections idling after a while is probably a sign that something's off.
I will check
Oh yes, there was tons of spammed connections after doing netstat -a
So i'm guessing something is leaking connections
how do you make the go routines, is it bounded... you should share the http client
I mean, you do have MaxIdleConns: 10000 set on your API client.
Yes, to see if that fixed the issue.
won't help if he isn't: #1251640256302682123 message
Reducing it to something reasonable could still help. Though idk, I don't think it should really matter if the client is only connecting to one host, it should just reuse that one.
Still, though, those high timeouts and everything sound bad.
Running this when an API client is discarded might help.
https://pkg.go.dev/net/http#Transport.CloseIdleConnections
func (t *Transport) CloseIdleConnections()```
CloseIdleConnections closes any connections which were previously connected from previous requests but are now sitting idle in a "keep-alive" state. It does not interrupt any connections currently in use.
Assuming the clients are created and discarded regularly.
I'll try something else, and I will let you know.
...
make sure you're calling NewApiClient only exactly once
how do you make the go routines, is it bounded... you should share the http client
calling CloseIdleConnections but making new transports/clients won't help
It'll close the connections immediately instead of having them stick around until the time.AfterFunc that'll close it after the timeout runs, would it not?
you do want to get connection pooling/reuse and for that you need to NOT make a new client for each request
Well, yeah, fixing the strange design choices would be better.
so sure, calling CloseIdleConnections (assuming there is a "end") would help a little bit but that's still not how you're supposed to use the http client
My developer is quite new to golang
We never had this issue in Python
Well, that didnt solve anything.
"that" being ?
I tried implementing backoff
func (c *ApiClient) postJSON(path string, data interface{}) (map[string]interface{}, error) {
body, err := json.Marshal(data)
if err != nil {
return nil, err
}
req, err := http.NewRequest(http.MethodPost, HOST+path, bytes.NewBuffer(body))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
var resp *http.Response
operation := func() error {
var err error
resp, err = c.httpClient.Do(req)
if err != nil {
return err
}
return nil
}
err = backoff.Retry(operation, backoff.NewExponentialBackOff())
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := ioutil.ReadAll(resp.Body)
if c.openLog {
log.Printf("Error: %d %s", resp.StatusCode, string(body))
}
return nil, errors.New(string(body))
}
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
return result, nil
}
Which infact did nothing
Doesn't really help if there's no ephemeral port to bind to.
I tried reducing it to both 1000, and 100. aswell.
it did nothing because
make sure you're calling NewApiClient only exactly once
how do you make the go routines, is it bounded... you should share the http client
I'm not the developer here, just trying to solve the issue since he is sleeping
I'm only calling it once as far as i'm aware
wait, maybe not
nvm, I am calling it once
how about you add a print in NewApiClient()
That was a commented function
If that "one" call is done once per gothread, then it's going to get called more than once.
The function where it is placed the second time is unused, nothing to worry about there
I've already wasted $100 debugging this ffs, and we have been at this issue for maybe 2 weeks now.
Well, as Moorea said, add a print to the start of NewApiClient to see if it really is only called once.
Its only being called once
I doubt it with your symptoms, did you really add the print? and you don't need to run more than 10 calls to debug
I added the print statement, and it looks like it's fine?
It's printing once after being called if i'm correct
Let me try something else
define "fine"? after each call or once total (for say 10 threads or whichever threads/go routine number you use)
Yes, I ran 10 threads. Which did 10 solves,
log.Printf("NewApiClient function called %d times.", newApiClientCallCount)```
Was printed 10 times.
so that's why...
So, if you do 20 solves, does it print 20 times?
and as I said what feels like a dozen times already, it should be 1 - when your developper wakes up, tell him to
share the http client
Yes.
So, each new solve incurs a NewApiClient call 🙃
1 solve = 1 print
I have the client, its 760 lines.
I have the full source code
If every single connection creates a new API client with a new http.Client, each configured to keep a connection alive for 90 seconds, and you create 15k connections within those 90 seconds, then those connections will be dutifully kept alive for 90 seconds and you'll run out of ports to bind to.
Just have one API client instance, period (as Moorea's been saying). Maybe one per worker thread or something. But one per connection and with each configured to hold on, for a long time, to resources it's not going to be around to use for very long is silly.
it's wasteful for both you (the client, churning new expensive to establish connections, and running out) and for the server you are calling repeatedly (though I guess if they are charging you for each, maybe they don't care)
Well, in that case I will try to get ahold of my dev in the morning. It seems to be too much for me to solve alone
Thank you both so much for the help eitherway
you could try to get chatgpt / copilot to fix it for you but basically it's making the http client a singleton (or even use the default one)
I did that too, it's not much help. AI is really shit
good 🙂 some basic human skills still needed 🙂
Hey!
func (ofSession Session) doFastHttpRequest(uri string, userId string, cookie string) (error, *fasthttp.Response) {
req := fasthttp.AcquireRequest()
req.SetRequestURI(uri)
sign, time := header.GetSignAndTime(uri, userId)
if userId == "0" {
userId = "none"
}
req = ofSession.SetFastHeaders(req, sign, time, cookie, false, userId)
res := fasthttp.AcquireResponse()
if err := ofSession.fastClient.Do(req, res); err != nil {
ui.PrintData(fmt.Sprint(err))
fasthttp.ReleaseResponse(res)
ui.AddInteger("errors")
return errors.New("NIGGA"), nil
}
fasthttp.ReleaseRequest(req)
return nil, res
}
func (ofSession Session) doFastHttpRequestPost(uri string, userId string, payload interface{}) (error, *fasthttp.Response) {
payloadBytes, err := json.Marshal(payload)
if err != nil {
return err, nil
}
req := fasthttp.AcquireRequest()
req.Header.SetMethod("POST")
req.SetBody(payloadBytes)
req.Header.SetContentType("application/json")
req.SetRequestURI(uri)
sign, time := header.GetSignAndTime(uri, userId)
if userId == "0" {
userId = "none"
}
req = ofSession.SetFastHeaders(req, sign, time, ofSession.cookieToUse, true, userId)
res := fasthttp.AcquireResponse()
if err := ofSession.fastClient.Do(req, res); err != nil {
fasthttp.ReleaseResponse(res)
ui.AddInteger("errors")
return errors.New("NIGGA"), nil
}
fasthttp.ReleaseRequest(req)
return nil, res
}
this is the part where we are facing that error
"ui.PrintData(fmt.Sprint(err))"
ofSession.fastClient = fasthttp.Client{MaxConnsPerHost: 100000000, Dial: fasthttpproxy.FasthttpHTTPDialerTimeout(ofSession.proxyUrl, timer.Second*60)}
ofSession.XHash = ofSession.GetXHash()
@heavy mist Here he is
you don’t need to use fasthttp, stick to stdlib and just make sure you have a single httpclient shared across requests
alr then
done? works now?