3

I came across an old service which listens on a range of TCP ports. Client connections are handled with this scheme:

  1. Client connects to the first port
  2. Server answers with a port number and closes the connection
  3. Client re-connects to the server-supplied port
  4. Business happens

Comments indicate that the author was insistent that, once a client connected to a port, that port was "in use". No other clients would be able to connect. Allegedly, the connection attempt would block. That is why the first "welcome" port needed to be "freed" as soon as possible.

Obviously, this does not make much sense today, but it made me wonder: Has there ever been a time or architecture which supported TCP/IP and multithreading, but could not handle more than one connection per TCP port?

The application is still running today on a Win2k server. The source is written in Pascal. No indication of when it was first conceived. My guess is early 90s, targeting DOS.

9
  • 1
    I don't think so (though I have no evidence). I expect the author was only testing from one IP address (probably 127.0.0.1), and got confused.
    – wizzwizz4
    Mar 5, 2021 at 13:24
  • 2
    Mind to link the source, and/or describe more of the environment? This is all about OS/communication software/libraries used and how they manage connections.
    – Raffzahn
    Mar 5, 2021 at 13:25
  • 5
    No. Stream connections in TCP have always been remote address/port-local address/port quads. Possibly a bug in the network stack of the OS (at that time), the language's library (at that time), or the author's understanding (at that time, as suggested by @wizzwizz4). There were - are! - protocols that (sort of) behave this way, e.g., ftp where you connect to the server on a "control" connection and then the server tells you the port where you need to connect for the data stream. (But in ftp you keep the control connection open as long as you'd like, e.g. for multiple data transfers.)
    – davidbak
    Mar 5, 2021 at 13:51
  • 1
    Unfortunately, I may not share the source. It is your typical in-house solution. Written decades ago, using outdated software even back then, running vital parts of modern corporations. ;)
    – Hermann
    Mar 5, 2021 at 15:14
  • This sounds like a security thing. The server is only allowing one connection per port to keep multiple connections to the service separate. Not the best security approach but probably good enough for the writers at the time.
    – Chenmunka
    Mar 5, 2021 at 16:32

3 Answers 3

7

Pascal/DOS/early 90s makes this answer not applicable to the old program mentioned in the question, but for the sake of completeness:

The original Network Control Program (NCP), which was obsoleted by TCP/IP in 1983, originally defined in RFC36 a connection table only indexed by the local port.

This would indeed mean for a server "listening" (if this terminology applies to NCP) on a local port, that as long as it has established a connection with an incoming client, then that port is in use. The only way to get rid of it would be to spawn a server subprocess, have this subprocess use a different server port, and tell the client to switch to the port.

I do not know if that was ever done for NCP.

1
  • This is the answer I expected. It is very possible the author of the software I was looking at was coming from this background.
    – Hermann
    Mar 5, 2021 at 15:09
5

It’s impossible to know without additional background on the history of the application or its author, which is either unavailable to you or you are unable to share. However there is a very good chance that this is just the result of a developer’s inexperience in any form of networking programming.

It’s not impossible, but I think that the chance of someone writing in-house corporate software in the late ‘90s who were also familiar with NCP (discontinued in 1983, before networks were common in all but the largest organizations) are really remote.

In the early ‘90s very few developers would have been experienced with network programming. Most people’s exposure to networks would have been limited to using (likely NetWare) file shares (*1). Technical resources and training were more limited and harder to reach than in today’s connected world. Your typical corporate in-house developer would have been primarily a domain expert, maybe self-taught in programming and writing programs for DOS standalone machines. They would have had perhaps one book available to them about how to program in TCP/IP and no expert available to lean against.

If you started writing a network application at the time (probably using Sockets) you would start coding right away, learning as needed without studying the protocol or library in full detail. Most of your attention would have been on the domain of the application, with the networking code being a small portion you needed to get working and then move on. You can go really far, even finish coding, without even realizing that there was such a thing as client ports. Even if the developer eventually noticed, there is a chance that they had been too committed by then to something that already worked, and decided to keep going.

I started my professional career in the late ‘90s surrounded by people who had more networking experienced than your typical corporate developer and maintaining a fairly sophisticated TCP/IP client-server application; and I still found several components that happily assumed that TCP/IP was packet-based (*2) and got away with it most of the time. The most well intended developers could get protocol concepts wrong. (I didn’t just show up with The Truth at hand of course, I was simply lucky enough to be given the needed time to study the documentation, then identify and fix the issues)

(*1) There is a small chance that they had been exposed to SPX/IPX network programming, but as far as I know SPX/IPX has a notion equivalent to TCP client and server ports, so that would not explain the misunderstanding. Someone correct me if I’m wrong because I have never actually written for SPX/IPX.

(*2) The assumption that (Winsock example) a single recv() call will get you the full message you are expecting from the sender. That is not guaranteed. TCP is a stream protocol and the sender doesn’t send packets but a sequence of bytes; you’re getting a stream of bytes chunked (in order) for efficiency reasons, but you don’t control chunk sizes. You have to know the size of the message (in advance or from stream data), you have to keep reading until you get all the chunks of your message, and you have to reassemble them yourself.

4
  • 1
    re In the early ‘90s very few developers would have been experienced with network programming. It depends how you define "few", I suppose. In my circles it was pretty mainstream by around 1980, though not specifically TCP/IP. Good comment about assumptions about TCP having packets/messages, by the way - still a problem with programmers today.
    – dave
    Mar 7, 2021 at 16:16
  • 1
    And too, there are also OS bugs, found the hard way. The code author's comment may mean "doesn't work, because it led to bugs traced to the network stack which we can't change", or it could mean "doesn't work, because it led to bugs that I never did figure out the root cause of (because I didn't suspect the network stack had bugs) thus that's just 'the way things work'". As late as 2016 I found a "bug" in Windows 2008 Server where under heavy load (due to a router failure mode) it would sometimes close a network socket without giving the documented callback, and I needed a workaround.
    – davidbak
    Mar 7, 2021 at 17:06
  • 2
    Also, +1 due to reminding us that not every programmer is omniscient (you know, besides me of course) and thus somethings things are coded or even designed the way they are because that was the best belief the programmer (or his entire team!) had at the time.
    – davidbak
    Mar 7, 2021 at 17:08
  • 1
    "Empirical computer science", a.k.a. "it worked in my test case".
    – dave
    Mar 7, 2021 at 20:40
1

Embedded systems often have insufficient resources to accommodate multiple simultaneous TCP connections. As a result, they will often deny an attempt to initiate a connection when a connection is already live, but time out live connections relatively quickly, so that if a connection is dropped the device will return to usability relatively quickly.

An approach I used on a bare-metal TCP stack I invented, but which I've not seen used elsewhere, was to have a device support a primary TCP port as well as a TCP "echo server", but watch for a certain magic sequence of bytes on the echo server as a cue to forcibly end the primary port connection.

The TCP echo server was implemented in entirely stateless fashion using a separate port, and could accept an essentially unlimited number of connections. Receipt of a SYN packet would send back a SYN+ACK with source and destination port and IP addresses flipped, and with both source and destination byte counters copied from the original. Receipt of any other ACK packet would return a packet with source and destination port, IP, and byte counters swapped, but use the difference between source and destination byte counters as a cue for what data to send (the port would send out a repeating message that included some status bits).

I think the response to SYN would be four bytes longer than the incoming packet, but otherwise all transmitted packets were the same length as incoming packets, and the echo server was entirely stateless, so the only form of denial-of-service attack would be a data flood, and that would require that the initiator of the attack use half as much bandwidth as to flood the target's connection.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .