[Cuis-dev] finding an open port

Mark Volkmann r.mark.volkmann at gmail.com
Tue Oct 29 06:17:40 PDT 2024


Martin, that was an excellent suggestion! The WebServerPlus class in my
WebClientPlus package at
https://github.com/mvolkmann/Cuis-Smalltalk-WebClientPlus now has this
class method which does exactly what I need.

openPort
    "Answer an open port number"
    | port socket |

    socket := Socket newTCP.
    socket listenOn: 0. "gets an ephemeral port"
    port := socket localPort.
    socket close.
    ^port.

On Sat, Oct 26, 2024 at 10:15 PM Martin McClure <martin at hand2mouse.com>
wrote:

> If you're just listening on an unused port for a test case, what would
> usually be done is to let the OS pick an open port for you. This is known
> as an ephemeral port or a sometimes a wildcard port.
>
> I don't know exactly how to do this in Cuis, but hopefully the VM used by
> Cuis allows you to do this. Typical APIs let you specify an ephemeral port
> by specifying 0 as the port number, and then provide some way to find what
> port number the system decided to use.
>
> Regards,
>
> -Martin
> On 10/25/24 06:35, Mark Volkmann via Cuis-dev wrote:
>
> I should have explained my use case. I'm using this in the setUp method
> for an SUnit test. It tests the endpoints of a web server. Previously the
> setUp method always started the server on a specific port. If that port was
> in use then the tests would fail. Now it always finds an available port and
> the tests pass regardless of whether specific ports are in use. If anyone
> is curious, you can see the code for the setUp and tearDown methods here:
> https://github.com/mvolkmann/Cuis-Smalltalk-WebClientPlus/blob/3eea948bc803aad814cc18932d7c57d45188b031/WebClientPlus.pck.st#L101
>
> On Fri, Oct 25, 2024 at 8:30 AM Jon Raiford <raiford at labware.com> wrote:
>
>> I think you are much better off grabbing the latest vm and using the
>> listenOn: code with an exception handler. Connecting to your machine in a
>> loop seems to be a backwards way to look for an unused port.
>>
>>
>>
>> Jon
>>
>>
>>
>> *From: *Mark Volkmann <r.mark.volkmann at gmail.com>
>> *Date: *Thursday, October 24, 2024 at 8:01 PM
>> *To: *Discussion of Cuis Smalltalk <cuis-dev at lists.cuis.st>
>> *Cc: *Jon Raiford <raiford at labware.com>, Gerald Klix <cuis.01 at klix.ch>
>> *Subject: *Re: [Cuis-dev] finding an open port
>>
>> I landed on a solution that seems to work fine. Does this seem reasonable?
>>
>>
>>
>> When I pass this 3000 and port 3000 is in use, it returns 3001.
>>
>>
>>
>> openPortFrom: aNumber
>>     | hostAddress port socket |
>>
>>     hostAddress := NetNameResolver addressForName: 'localhost'.
>>     port := aNumber.
>>     socket := Socket newTCP.
>>
>>     [ true ] whileTrue: [
>>         [
>>
>>             socket connectTo: hostAddress port: port
>> waitForConnectionFor: 1.
>>
>>             socket disconnect.
>>
>>             port := port + 1.
>>
>>         ] on: ConnectionTimedOut do: [ :ex | ^ port ].
>>
>>     ].
>>
>>
>>
>> On Thu, Oct 24, 2024 at 11:45 AM Jon Raiford via Cuis-dev <
>> cuis-dev at lists.cuis.st> wrote:
>>
>> For what it’s worth, the way I looked at his code was that the “listenOn:
>> port” should have thrown an RTE as the OS knows immediately that the port
>> is not available. Of course Mark’s code below doesn’t handle errors there,
>> but that would have been resolved during debugging. Whether or not the rest
>> of the code is sane is another matter entirely 😊.
>>
>>
>>
>> Jon
>>
>>
>>
>> *From: *Cuis-dev <cuis-dev-bounces at lists.cuis.st> on behalf of Gerald
>> Klix via Cuis-dev <cuis-dev at lists.cuis.st>
>> *Date: *Thursday, October 24, 2024 at 12:25 PM
>> *To: *cuis-dev at lists.cuis.st <cuis-dev at lists.cuis.st>
>> *Cc: *Gerald Klix <cuis.01 at klix.ch>
>> *Subject: *Re: [Cuis-dev] finding an open port
>>
>> Dear Mark,
>>
>> why in name of Alan (Perlis) do you expect a connection to your newly
>> created server socket pop out of nowhere?
>>
>> Increase the time out to 60 in `connected := socket
>> waitForConnectionFor: 1 ifTimedOut: [ false ].`,
>> send the #openPortFrom: message to your object.
>>
>> Switch to Terminal window, and start telnet like this
>> `telnet 127.0.0.1 3000` and marvel at the results.
>>
>> Sorry for my harsh words: This issue has nothing to do with Cuis,
>> but a lot with socket, bind and listen.
>>
>> See man 2 bind, man 2 listen
>>
>>
>> Just my 0,01€,
>>
>> Gerald
>>
>>
>>
>> On 10/24/24 2:29 AM, Mark Volkmann via Cuis-dev wrote:
>> > I wrote the following code to take a port number and return the first
>> port
>> > starting from that number that is open. For example, if ports 3000 and
>> 3001
>> > are in use and I send "MyClass openPortFrom: 3000" then I expect it to
>> > return 3002. Can you spot why this never finds an open port and loops
>> > forever?
>> >
>> > openPortFrom: aNumber
>> > | connected port socket |
>> >
>> > connected := false.
>> > port := aNumber.
>> >
>> > [ connected ] whileFalse: [
>> > 'trying port {1}' format: { port } :: print.
>> > socket := Socket newTCP.
>> > socket listenOn: port.
>> > connected := socket waitForConnectionFor: 1 ifTimedOut: [ false ].
>> > connected ifTrue: [socket disconnect] ifFalse: [ port := port + 1 ].
>> > ].
>> >
>> > ^port.
>> >
>> >
>>
>> --
>> Cuis-dev mailing list
>> Cuis-dev at lists.cuis.st
>> https://lists.cuis.st/mailman/listinfo/cuis-dev
>>
>> --
>> Cuis-dev mailing list
>> Cuis-dev at lists.cuis.st
>> https://lists.cuis.st/mailman/listinfo/cuis-dev
>>
>>
>>
>>
>> --
>>
>> R. Mark Volkmann
>>
>> Object Computing, Inc.
>>
>
>
> --
> R. Mark Volkmann
> Object Computing, Inc.
>
>

-- 
R. Mark Volkmann
Object Computing, Inc.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20241029/3bffe306/attachment-0001.htm>


More information about the Cuis-dev mailing list