1

I would expect having multiple servers on the same port would cause problems. In fact I want it to throw an exception when I try to start two servers on the same port. The problem is, it seems more than happy to start multiple servers on the same port. I can have many instances of the following code running just fine with no exceptions.

import BaseHTTPServer
import SimpleHTTPServer
import sys

def main():
    try:
        server = BaseHTTPServer.HTTPServer(('127.0.0.1',5000), SimpleHTTPServer.SimpleHTTPRequestHandler)
        print "On port: " + str(server.socket.getsockname()[1])
    except Exception, e:
        print e
    server.serve_forever()

if __name__ == "__main__":
    main()

All of which claim to be on port 5000. How can I get it to throw an exception if it tries to use a port that is already taken?

Edit: This is Python 2.6.4

Edit 2: http://www.youtube.com/watch?v=rVOG3JdbHAM&feature=youtu.be Because people seem to think what I am explaining is not possible? Or I am totally misunderstanding people. Either way, this video should clear it up. I start two servers, neither of them print out any exceptions. When I close the first, the second starts working. Why is this happening? I would expect the 2nd server to simply never start and print an exception. Is this not what should happen?

Justin
  • 2,322
  • 1
  • 16
  • 22
  • 2
    Umm, you're hiding the exceptions. This will immediately terminate if the initialization fails (`server` won't be set). – phihag Jul 19 '12 at 22:37
  • Yeah, I am aware of that. This is just a simple snippet that illustrates my problem of having many servers on the same port. – Justin Jul 19 '12 at 22:48
  • 2
    You must be mistaken, the underlying os won't allow two processes to open a socket server on the same port. There must be more to the story. – Bryan Oakley Jul 19 '12 at 23:00
  • Running Python 2.7 on Windows 7; I get the same issue. – GrantVS Jul 19 '12 at 23:20
  • Is the code in this question absolutely the only code you are running, or are you paraphrasing? – Bryan Oakley Jul 19 '12 at 23:29
  • This is absolutely the only code I am running. Just to confirm it I 1) copied and pasted it into a new file. 2) ran that file in two different command prompts. 3) saw no exceptions and saw the message On port: 5000 on each. The first console will output messages when I navigate to it. If I close it, the 2nd console will then start printing out the messages as I navigate to it. If I had screen recording software, I would post a video on YouTube :) – Justin Jul 19 '12 at 23:36

3 Answers3

1

I tried to execute your code and the second instance returned,

 [Errno 98] Address already in use

as it should. Python 2.6 on SuSE Linux.

Can check with netstat utility whether port 5000 is really taken?

LSerni
  • 55,617
  • 10
  • 65
  • 107
  • I am running on Windows 7. It lists the ports status as TIME_WAIT. – Justin Jul 19 '12 at 22:45
  • Okay, so it is NOT listening. The server did not even start (I don't know why). The port should be in LISTEN mode if displayed with "netstat -na". – LSerni Jul 19 '12 at 22:50
  • But what is odd is that it still works. If I wait long enough, run netstat again, 127.0.0.1:5000 is not even listed. But if I navigate there in a browser, the correct files are served and the port is again listed as TIME_WAIT. (And if I use a different port no files are served) – Justin Jul 19 '12 at 22:53
  • The port working without being in LISTEN would shriek "rootkit!" under any Unix. Maybe windows 7 has a different policy; check out the TCPView utility by SysInternals. Maybe there's some really weird socket multiplexing scheme to allow more servers on a port. Maybe port 5000 is interfered upon by the uPNP subsystem. I'm sorry, I have next to no experience on Windows 7 networking :-( – LSerni Jul 19 '12 at 22:58
0

A TCP port can be bound by one and only one process. As was noted by @phihag, you only think you have multiple servers bound to port 5000 because you are throwing away the exception that would tell you that you already had bound that port.

I am running on Windows 7. It lists the ports status as TIME_WAIT

That's a secondary problem which is usually caused by clients not shutting down the connection properly. TIME_WAIT is a valid TCP state but one that will take 2 minutes for the server to clear. You should look to why your clients are dropping the connection instead of having the server close it.

If you are using a standard browser on the client side, you should assume you have a second bug in your server code that you've not shown here.

added in response to comment

There is something wrong with your expectations. This version of your code should make it clear:

def bind():
    return BaseHTTPServer.HTTPServer(('127.0.0.1',5000), SimpleHTTPServer.SimpleHTTPRequestHandler)

s1 = bind()
s2 = bind()

Where the last line will abort your program with an "Address already in use" exception. If you chose to ignore (or catch and discard) the exception, s2 will not be have a valid server. This is what the exception is telling you. In C, if you ignored errors the same way it would look like:

fp = fopen("a_file_that_does_not_exist", "r")
fgets(buf, BUFSIZ, fp)

Both fopen and fgets will return EOF which you are ignoring. The program would run, but it certainly wouldn't do anything useful because you can't read from a file that does not exist. You can ignore the error returns but holding your hands over your eyes doesn't make the monster go away either.

msw
  • 42,753
  • 9
  • 87
  • 112
  • I must be confused as to what you and phihag mean about throwing away the exception. (New to Python) I thought by having the except block I was catching and printing exceptions raised when starting the server. It seems to correctly capture and print an exception when I set it to a port that netstat lists as ESTABLISHED. – Justin Jul 19 '12 at 23:06
  • 1
    Catching an exception does **not** handle the exception. Suppose you were opening a file for reading that didn't exist, it would raise an exception. Catching that exception and printing a message would **not** leave you with an readable file, it would let your program continue with an unreadable file "handle". Every `file.read()` would thus fail; therefore, you "caught" the exception but didn't fix the problem of "no file to read". You are doing the same thing here, but files are a little easier to visualize than sockets. – msw Jul 19 '12 at 23:11
  • Ok. So this is still doing what I expect then. I am not trying to actually switch to a backup port in this example. This is just to illustrate that I am not getting any exceptions when I try to open two servers on the port. – Justin Jul 19 '12 at 23:16
  • @Justin see "added" above in my answer. Your expectation is wrong. – msw Jul 20 '12 at 00:14
  • So, maybe I am not understanding what my code does here. But What I think SHOULD be happening when I open the 2nd server on the port, I should get an error message that, paraphrased, says something like "Port already in use sucker, I am not going to server nothing for you!". When in fact, what ACTUALLY HAPPENS is I get the message "On port: 5000". And if I close the 1st instance of the server, the 2nd instance continues to work on port 5000. It should not work, but does. Once I can actually make it not work, I can replace the except block with something useful. Like opining a different port. – Justin Jul 20 '12 at 03:29
0

I agree with the various answers and comments indicating that you cannot have multiple listeners to a single TCP port; however, I am experiencing the same behaviour as OP. I am running Windows 8, and neither instance of my program (written in C++, using Boost) has an exception thrown. The output from netstat looks like:

C:\windows\system32>netstat -an

Active Connections

  Proto  Local Address          Foreign Address        State
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING
  TCP    0.0.0.0:5357           0.0.0.0:0              LISTENING
  TCP    0.0.0.0:7112           0.0.0.0:0              LISTENING
  TCP    0.0.0.0:17500          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:49152          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:49153          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:49154          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:49155          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:49157          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:50102          0.0.0.0:0              LISTENING
  TCP    0.0.0.0:50102          0.0.0.0:0              LISTENING
  TCP    127.0.0.1:2559         0.0.0.0:0              LISTENING
  TCP    127.0.0.1:19872        127.0.0.1:49248        ESTABLISHED
  TCP    127.0.0.1:49248        127.0.0.1:19872        ESTABLISHED
  TCP    127.0.0.1:50102        127.0.0.1:52616        TIME_WAIT
  TCP    127.0.0.1:50102        127.0.0.1:52618        TIME_WAIT
  TCP    127.0.0.1:50102        127.0.0.1:52620        TIME_WAIT
  TCP    127.0.0.1:50102        127.0.0.1:52622        TIME_WAIT

In this case, the first program instance to start listening to port 50102 receives all the client connections. Then, when I close that instance, the second instance starts receiving the client connections. Strange but true.

I was hoping that the second program instance would be unable to start listening to the same port as the first instance.

dhdawe
  • 1