且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用watir-webdriver打开多个线程会导致“连接被拒绝"错误

更新时间:2023-10-26 19:03:22

基本上,您正在创建浏览器实例之间的竞争条件,以连接到watir-webdriver找到的开放端口.在这种情况下,浏览器的第一个实例将看到端口9517已打开并连接到该端口.因为您正在并行拆分这些实例,所以第二个实例还认为端口9517已打开并尝试连接.但是,哎呀,第一个浏览器实例已经在使用该端口.这就是为什么您会收到此特定错误.

这也解释了为什么sleep 2解决此问题的原因.第一个浏览器实例连接到端口9517,休眠使第二个浏览器实例看到采用了9517.然后,它在端口9518上进行连接.

编辑

您可以看到如何使用Selenium::WebDriver::Chrome::Service#initialize(此处).网络驱动程序通过PortProber确定打开哪个端口.

I have this simple example:

require 'watir-webdriver'

arr = []
sites = [
"www.google.com",
"www.bbc.com",
"www.cnn.com",
"www.gmail.com"
]

sites.each do |site|
    arr << Thread.new {
        b = Watir::Browser.new :chrome
        b.goto site
        puts b.url
        b.close
    }
end
arr.each {|t| t.join}

Every time i run this script, I get

ruby/2.1.0/net/http.rb:879:in `initialize': Connection refused - connect(2) for "127.0.0.1"      port 9517 (Errno::ECONNREFUSED)

Or one of the browsers closes unexpectedly on atleast one of the threads.

on the other hand, if i set sleep 2 at the end of every loop cycle, everything runs smoothly! Any idea why is that?

Must be something related to understanding how threads work...

You're basically creating a race condition between the instances of your browser to connect to the open port watir-webdriver is finding. In this case, your first instance of the browser sees that port 9517 is open and connects to it. Because you're spinning up these instances in parallel, your second instance also thinks port 9517 is open and tries to connect. But oops, that port is already being used by the first browser instance. That's why you get this particular error.

This also explains why the sleep 2 fixes the issue. The first browser instance connects to port 9517 and the sleep causes the second browser instance to see that 9517 is taken. It then connects on port 9518.

EDIT

You can see how this is implemented with Selenium::WebDriver::Chrome::Service#initialize (here), which calls Selenium::WebDriver::PortProber (here). PortProber is how the webdriver determines which port is open.