Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations John Tel on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Winsock won't connect... 3

Status
Not open for further replies.

OrthoDocSoft

Programmer
May 7, 2004
291
US
Folks,

I'm at work at my hospital, where I'm beta testing my software. I cannot really look at my code, so I can't give you specifics right now, but I took a winsock control and dropped it in the listener. I added text boxes for the IP address and Port number, and hooked it all up and it works at home against an HL7 Server that I wrote to debug the listener. I set the listenerk at home to:

IP 127.0.0.1, and,
Port 1412.

And this all worked well. The server could send messages at almost 1/millisecond, and I seemed to receive them on the listener without incident.

At work, where my beta test site is, My HL7 listener is sitting on a different server than the HL7 server now sending. I'm talking to my HL7 guy here and he is sending on:

IP 172.17.1.172 and,
Port 7227

But when I try to connect, it doesn't connect.

Without seeing my code, can anyone figure out why this doesn't work in real life? It seemed so easy on my development computer at home.

Thanks,

Ortho

[lookaround] "you cain't fix 'stupid'...
 
Welcome to the world of firewalls!

Often times, the firewall blocks your communications between computers. There can be multiple firewalls blocking you. Your server could be running a firewall. Your client could be running a firewall, and there can be any number of routers between the computers also running a firewall.

If you are using the built-in windows firewall, the easiest way to "get to it" is to click Start -> Run, type FIREWALL.CPL, click OK.

There are 3rd party firewall applications that may be running on your computers too (ZoneAlarm is a popular one). Regardless, if you have firewalls blocking you, you will not be able to communicate over tcp/ip. All firewall's have configuration settings to unblock any port you want. Some allow you to block incoming, outgoing, or any combination.

Routers also have firewalls built in to them, so you may need to configure the router to allow certain ports through them.

Whatever you do, if you determine this is a firewall issue, do NOT turn off the firewall. Figure out how to configure the firewall to allow your app to communicate. Since you appear to work for a hospital, I would guess that you have network administrators there that know how to do this sort of thing, you may want to start by having a conversation with them about this.

Now, I'm not saying this is your problem, but it is the first place I suggest you look.

-George

"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
I'm twisted around on this again.

The end being called "listener" here... does it "listen" for an incoming connection? If so, by definition it is the server in TCP terms.

A TCP server should listen on a specific port number that is used by TCP clients along with its IP address (or DNS name) so they can connect to that server. The TCP server should not specify a LocalPort value and normally never specify a LocalIP value. The server should specify this LocalPort value by using the Bind method prior to calling the Listen method.

A TCP client should normally connect by using a Connect call specifying the RemotePort that the server is bound to, along with the IP address or DNS name of the TCP server. LocalPort should be set to 0 before calling the Connect method, resulting in the TCP stack allocating an unused ephemeral port number and assigning it to the socket.

The LocalPort number used by the client (the end calling Connect) is unimportant... aside from the fact that no other connection can be using the same port with the same remote host via the same TCP adapter of the local host.


HL7 connections may well invert the use of the terms client and server, or maybe it doesn't. But unless you have multiple Ethernet adapters (or virtual adapters) the end that calls Bind and then Listen should not be specifying IP addresses at all. The client end which calls Connect should set LocalPort to zero (0, the initial default value) and then call Connect specifying the server's bound port number and IP address (or DNS name).

Where possible you don't want to be using IP addresses explicitly anyway. This is why we have DNS: to use seldom-changing symbolic names instead of more frequently changing IP addresses. 127.0.0.1 corresponds to the name localhost and is normally an alias used to refer to the system the code is running on.


If your "listener" is a TCP client (i.e. it calls Connect) you should be setting LocalPort to 0, then calling Connect specifying a port 7227 and a name (if available) or corresponding IP address of 172.17.1.172 in order to reach the TCP server. If the other end is acting as the client and wants to connect to 7227 then you should Bind to 7227 and then Listen.

But in any case only one TCP port number is normally of significance in establishng connections. The other should be system allocated from a pool of unused ports (thus the 0) so that a unique value is chosen. Trying to specify both is a recipe for disaster, since the 4-tuple that uniquely identifies a TCP connection is not immediately released upon a disconnect. An active connection is identified by 4 values taken together:

((Local Port, Local IP), (Remote Port, Remote IP))

This is used by TCP protocol stacks to maintain the "fiction" that is a TCP connection - connections are entirely virtual. Each pair of values is called an "endpoint" and a pair of endpoints identifies a connection. Until both ends do a graceful close on an established connection, the connection stays in the TCP stack's tables because there may have been a transient disruption. If about 4 minutes go by while the connection is in this state (typically called TIME-WAIT internally) then the connection is abandoned and that 4-tuple becomes available once again.


I go into all of that because newbies often try to over-specify connection parameters and get themselves bound up in trying to reuse a TIME-WAIT connection. The other thing they do is get confused about what port to specify. The client RemotePort is like a "plug" that has to match the "socket" LocalPort at the server end. The "shape" of this plug and socket are a single TCP port number. The reverse "plug and socket" are negotiated as part of session establishment.

You can violate this contract by over specifying (i.e. having the connecting application specify a fixed LocalPort, sometimes referred to as "source port") but usually it has undesired consequences. Normally you set it to 0 prior to each Connect call, which results in an unused value being assigned.


But my guess is that you are doing a Listen (probably without a Bind - for shame!) on 1412 while he is trying to do a Connect on 7227.
 
Are you taking you computer to work to test it or are you just installing it on the work computer?

If the former you may have to set your TCPIP subnet and gateway settings to ones allocated by the network administrator on both computers if the network is configured to only allow communications on certan values of these.

 
George and Dilenttente,

I JUST found this error in my code. Do you think this could be it plain and simple?
Code:
Winsock1.Close

Winsock1.RemoteHost = txtIP.Text
Winsock1.RemotePort = txtPort.Text '(notice I'm using a string when this parameter is a long value)

Winsock1.Connect

I will correct it to:

Code:
Winsock1.RemortPort = CLng(txtPort.Text)

George, your bits about firewalls I was already on to just after posting, but thank you so much for pointing out the importance of checking all that, and I will.

Dilettante, I grooved on most of what you said, but I'm going to archive this post to try to fully understand it. As a TCP/IP noob, I only know about "ports" and IP addresses, one each for a PAIR of clients and servers (in other words, A client and server pair only need ONE port and ONE IP address to talk about).

I think you are saying that is not quite the case. I'll report back tomorrow as to what effect the error had.

I'm not sure about the "localport" thing. Let me study what you've said.

Stars later. If you give them out too soon, people think your problem is solved. Elegant, elegant respones, both of you.

thanks much,

Ortho

[lookaround] "you cain't fix 'stupid'...
 
Ted,

Wow, just posted my response, and then saw yours.

The latter. I develop at home in my spare time, and I have my compiled app installed at my hospital. I really shouldn't post questions from there since I don't have my source code handy, but I get weak.... Today was the FIRST day I ever tried to communicate with TCP/IP through a device I have written.

Failure, just like it always is.

At first. (And I will die trying to fix any error my stuff has.... Development is an freakin' blast!)

Thanks,

Ortho

[lookaround] "you cain't fix 'stupid'...
 
If you are calling Connect in your code, you can either set the RemoteHost and RemotePort as you have above or as optional parameters to Connect itself.

Using the .Text property as you have is not the problem, the compiler will implicitly insert the CLng() though it is always good to be explicit about it.

If your program will be calling Connect more than once during its lifetime you want to set LocalPort to 0 before each Connect. Since it defaults to 0 most people don't realize they have a problem until later though.

If the other guy is listening for connections on 7227 you have to set RemotePort to 7227, not some other random value like 1412. If you were already using 7227 and that isn't working you have some other issue. Connecting outbould should not be impeded by Windows Firewall on your machine though. Beware that many 3rd party firewall products get snippy about any outbound connections besides a few preset port numbers though.

Aside from an IP address typo I'm not sure what else might be at work here. Can you ping the other machine from yours?

Command prompt:

[tt]ping 172.17.1.172[/tt]

Of course you want to be at VB6 SP6 so you have the most recent usable version of the Winsock control too. There were numerous small flaws up until then.

We can only hope you haven't installed any of the buggy "cumulative update rollup" packages Microsoft has released in the past year. We know of at least one new Winsock control bug Microsoft introduced in those. The good news is that Windows Update does not deliver these, you have to slit your own throat manually to end up in that position.

As far as I know DO NOT INSTALL THIS OR SIMILAR "UPDATES" GOING BACK TO AROUND DECEMBER 2008! Beware (most recent failed attempt): Description of the cumulative update rollup for the Visual Basic 6.0 Service Pack 6 Runtime Extended Files. I get the idea they have been assigning sutdent interns to work on the VB6 products lately. These updates break several controls you may require. DO NOT INSTALL THEM.

I would be happy to be corrected by anyone with better information though.
 
Dilettante,

I have tried to absorb your meaty post, and I believe I do, and did, understand it. You did, however, clear up some things.

My HL7 "listener" is, indeed, a TCP "client" that uses the connect method. Where I think I was confused at home, using 127.0.0.1, what I thought the CLIENT was "specifying" that IP address TO the SERVER, not the other way around where the Client was calling the IP address demanded by the location of the server, as you elegantly pointed out.

When I specified "localhost", aka, 127.0.0.1, I didn't realise that that was DEMANDED by the TCP server, since I obviously wrote one of those as well to debug the TCP client against, and it was "sitting on 127.0.0.1." So in my mind, I had "who's in charge" reversed.

Take home message from what you said: "Point your TCP client to the SERVER's IP address." (or DNS designation -- another elegant lesson learned). And I will try that. No wonder it failed. I was pointing my client to itself (you can't fix 'stupid').

I will explicitly set "LocalPort" to 0, but by your discussion, this was true in my client already by default, so maybe no big mistake. But it's nice to have that explanation of localport.

But as an aside about the HL7 "listener", aka, TCP client, IT (this listener-client) is the box that "listens" for HL7 messages being send out by the server, using its Winsock1.DataArrival method. So while a TCP SERVER listens for the TCP CLIENT to connect through the client's "connect" method, the HL7 LISTENER, aka, TCP ClIENT "listens" for messages the TCP SERVER sends, once the connection has been made. So the listening roles get reversed in that sense, and that is what I meant by "listener." And I understood what you meant that, in TCP-think, it's the Server that "listens" for the client, and binds that client.

I'm belaboring this a bit so others following along here can ponder it a bit.

I'll make the corrections tomorrow and get back to you all.

Thanks much,

Ortho

[lookaround] "you cain't fix 'stupid'...
 
Dilettante,

I think it's "who's IP address to use" that I discussed, that is, then, the likely problem....

Ortho

[lookaround] "you cain't fix 'stupid'...
 
It is really, really easy to to wrapped up in relative terminology with this sort of thing.

I sort of went on and on (and on) above in an attempt to try to stuff as many viewpoints into my response as I could, hoping to hit the right issue and perhaps providing some useful input on it. I was concerned that you might be confusing "listener" with calling Listen, so at least we don't have that added bit of Who's on first? to contend with.

Ideally we'd have more words for these sorts of things.

You might have a box running headless, as a "server" that may even be running a Server edition of Windows. Yet that server might run a program (possibly running as a Windows Service) that acts as a TCP "client" connecting back to a desktop system (itself acting as a TCP "server"). Then throw in the HL7 "listener" concept...

Yep, it can get liguistically convoluted.

But it does sound like you have enough to test again. Your HL7 Listener program would connect to the "server" using the server's IP address and the port number that the service is listening on. Sure sounds simple now.

Whew! Good luck on your next test.
 
Small comments at work:

first of all, I had a typo in the fourth line of my post, 2 posts ago. The incorrect line reads:

...using 127.0.0.1, what I thought the CLIENT....

while the correct line SHOULD read

...using 127.0.0.1, WAS I thought the CLIENT.....

Dilettante,

Yes, I am able to ping the correct IP address with <1ms response times. 4 packets sent, 4 packets received. 0 packets dropped.

When I put into my TCP client (HL7 listener), the IP address of the TCP server, as well as the port it is binding on 7227, it still did not work.

My IT guys are working on seeing if it is a firewall issue.

[lookaround] "you cain't fix 'stupid'...
 
Guess what?

We BOTH were acting as TCP CLIENTS! DHOH!!!

(You know, if development were easy, EVERYBODY would do it)

Ortho

[lookaround] "you cain't fix 'stupid'...
 
By the way,

The winsock can be a TCP SERVER, AND still "listen" for messages being sent to it utilizing Winsock1.DataArrival method, right?

Ortho

[lookaround] "you cain't fix 'stupid'...
 
Yes of course in that sense. It is better to use the term "listen" to mean the activity of awaiting incoming client connections though.

Once a connection is established it resembles two similar unidirectional pipes "pointed" in opoosite directions. This allows full duplex communication using the same set of methods and events at each end.
 
< same set of methods and events at each end.

But using the different remote IP addresses of each computer for each direction.

You only use listen on the 'server' side and 'connect' on the client side but once connected you use a Sub DataArrival for both ends to receive data from the other and SendData to send it from either end.

Once connected you dont use 'listen' any more unless you disconnect or lose connection and want to reconnect.

Any computer could be a number of servers and clients at the same time to a variety of other computers using the same IP address but different ports for each, all on the one ethernet cable or to a second application on the same computer (using the 127.0.0.1 address).
 
I think you missed my point Ted. Once the (single) connection is established it is bidirectional, and each end can use SendData/GetData and will see DataArrival events.

There is no need to establish a second connection in the other direction after the first is in place.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top