Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Strange things are done in the midnite sun by those who thread

  1. Apr 26, 2016 #1
    SO fun story, I'm working on a client server dealio!

    The flow of operations should be:
    Server listens on port 9999
    Client connects to port 9999
    Server tells Client to connect to new port # (to allow for more connections)
    Server launches a thread and listens on new port #
    Client disconnects from 9999 and connects to new port number
    PROFIT!

    I had originally got this all working where the client and the server were on the same computer.
    Today I decided to start to run the clients on a different computer.

    So the client connected to 9999
    got the message to use the new port number
    and then would get a connection refused on the reconnect. This happened like 90-95% of the time.. But occasionally just occasionally it would work??

    Fast forward an hour of scratching my head trying to figure out what the heck is going on. Turns out when I ran the client on this computer the the client would run just slow enough for the server to launch the thread and listen.

    When I ran it on the other laptop it was trying to connect before the listen was done on the server.
    A simple reordering so the server listens before telling the client to reconnect and everything works fine!

    Fun times:)
     
  2. jcsd
  3. Apr 26, 2016 #2

    Ibix

    User Avatar
    Science Advisor

    Ain't race conditions fun to debug?

    You know the story about the engineer who goes to hell? The Devil shows him a room full of electronic items and says his punishment is to fix them. The engineer doesn't think that's too bad. "Ah", says the Devil, "but all the faults are intermittent..."
     
  4. Apr 26, 2016 #3

    jedishrfu

    Staff: Mentor

    Its like counting your chickens before they hatch...
     
  5. Apr 26, 2016 #4
    Great... I"m going to have nightmares now about this....
     
  6. Apr 26, 2016 #5

    rbelli1

    User Avatar
    Gold Member

    Once you accept the TCP/IP socket the original port will be available for connection. You don't need to corral the client to another port. At least this is true of *NIX and Windows servers and almost everything internet facing. What operating system are you using?

    BoB
     
  7. Apr 26, 2016 #6
    Just running it off of windows 7, written in python.

    I'll try that out tomorrow rbelli1 and see if it works.
     
  8. Apr 26, 2016 #7

    jedishrfu

    Staff: Mentor

    I don't think this is right. If your program connects does its business and then disconnects then the port is available. Web applications do this.

    However, if this is a strict client/server connection sing say Java with multiple clients then you might need to use the OP's scheme of port reassignment to allow each client to keep the port open.
     
  9. Apr 26, 2016 #8

    rbelli1

    User Avatar
    Gold Member

    I've written server apps and I just listen on a particular port and then accept. No further connection is required. The listening socket is re-enabled for more connections.

    Think about how a web server works. Thousands of clients connect at the same time to the same port. If everyone had to wait for a transaction to occur then the web would screech to a halt. As I type I have a persistent connection to physicsforums:https. Presumably I am not the only one able to access this site.

    BoB

    edit: and wordpress:https and a number of Microsoft servers and some that can't do reverse dns.
     
  10. Apr 27, 2016 #9

    Ibix

    User Avatar
    Science Advisor

    Sorry. :wink: I agree with rbelli1, by the way. I may be able to dig out some elderly python code to illustrate this - I'll have a look.
     
  11. Apr 27, 2016 #10

    Ibix

    User Avatar
    Science Advisor

    As promised, here's a not-terribly-good chat server and client. Start the server first, and 2+ instances of the client. Just type at the prompt in the client command windows and hit enter to broadcast. The next time you type something and hit enter in any other client window, everything that has been said by anybody since the last time you typed will appear. It's functional as a use of sockets (which was the point of this), but not really as an actual chat client. Note that the server simply retains the connection returned by socket.accept() - there's no disconnect-and-reconnect.

    Note also that it's slightly elderly python 2.7 - I don't know how much difference that might make to sockets.

    Server:
    Code (Python):

    import socket

    def notifyAll(conns,c,data):
       for conn in conns:
         if len(conn)==3 and conn[1]!=c[1]:
           print "...notifying "+conn[2]
           conn[0].sendall(data+"\n")

    HOST=""
    PORT=12345

    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.setblocking(0)
    s.bind((HOST,PORT))
    s.listen(1)
    connections=[]
    gotConnection=False
    while True:
       # See if any new clients want to connect
       try:
         conn,addr=s.accept()
         print 'Connected by', addr
         conn.setblocking(0)
         connections.append([conn,addr])
         gotConnection=True
       except:
         pass
       # Print any data and close the connection if a QUIT was received
       for conn in connections:
         try:
           dataLine=conn[0].recv(1024)
           if dataLine=="QUIT":
             print conn[2]+" quit"
             connections.remove(conn)
             notifyAll(connections,conn,conn[2]+" quit\n")
           elif len(conn)==2:
             print str(addr)+" is called "+dataLine
             conn.append(dataLine)
             notifyAll(connections,conn,conn[2]+" joined\n")
           else:
             print "Received from "+conn[2]+": "+dataLine
             notifyAll(connections,conn,conn[2]+": "+dataLine+"\n")
         except:
           pass
       # Quit if all connections have been closed
       if gotConnection and len(connections)==0:
         break
    s.close()
     
    Client:
    Code (Python):

    import socket

    HOST="localhost"
    PORT=12345
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect((HOST,PORT))
    s.setblocking(0)
    inputLine=raw_input("Please enter your name: ")
    while True:
       s.sendall(inputLine)
       try:
         while True:
           dline=s.recv(1024)
           print dline
       except:
         pass
       if inputLine=="QUIT":
         break
       inputLine=raw_input("> ")
    s.close()
     
     
  12. Apr 28, 2016 #11
    I looked at my code yesterday and decided it was too complex to try and test it without changing the ports. One of those if its working lets not break it situations :)

    But out of curiosity if you have multiple clients connecting from the same IP and to the same port, how does the OS/Python determine which connection to send the data to?
     
  13. Apr 28, 2016 #12

    rbelli1

    User Avatar
    Gold Member

    The port at the client end is different for each connection. When the client opens the port it gets a local port assigned by some OS defined method.

    Server side -->> Client side
    192.168.1.1:80 -->> 192.168.1.2:1234
    192.168.1.1:80 -->> 192.168.1.2:1235
    192.168.1.1:80 -->> 192.168.1.2:1236
    and possibly other computers on the network
    192.168.1.1:80 -->> 192.168.1.3:1234
    192.168.1.1:80 -->> 192.168.1.4:1234
    192.168.1.1:80 -->> 192.168.1.5:1234

    BoB
     
  14. Apr 28, 2016 #13

    Ibix

    User Avatar
    Science Advisor

    If you run the code I posted you'll see that addr, the second variable returned by socket.accept, is what rbelli1 is describing, encoded as a two element tuple.
     
  15. Apr 28, 2016 #14
    Yes I forgot about the src port.

    I'm now not sure how I got the model of being pushed to a different port in my brain hole.
     
  16. Apr 28, 2016 #15
    You need to learn how to use tcpdump and wireshark, these are some of the most important tools in LAMP.
     
  17. Apr 28, 2016 #16

    Svein

    User Avatar
    Science Advisor

    "accept() is used on the server side. It accepts a received incoming attempt to create a new TCP connection from the remote client, and creates a new socket associated with the socket address pair of this connection." See https://en.wikipedia.org/wiki/Berkeley_sockets
     
  18. Apr 29, 2016 #17
    I'm going to have to go through my notes from the networking class I took.

    I'm confused as to how I got in my mind that for example.
    Apache2 listened on port 80, and then upon a connection forked itself and pushed the connection to a different random socket # to handle the session.
     
  19. Apr 29, 2016 #18
    Sort of. When a process listens on a port and allows multiple connections there are two ways that it handles it. It can actually handle many connections to the same socket because the source ip is always different (this is TCP specific) so it can filter and send things to the right socket.

    The only time it pushes the connection somewhere random is when you have multiple connections from the same machine.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: Strange things are done in the midnite sun by those who thread
  1. Strange error (Replies: 4)

  2. FORTRAN strange issue (Replies: 7)

  3. Strange response (Replies: 1)

Loading...