PDA

Click to See Complete Forum and Search --> : Winsock Problem


jonaxse
Nov 2nd, 2000, 01:12 AM
Hi,
I got a problem with Winsock you might have answers to.
Here is the situation:
I experimented with a client/server app in one machine only. I have a form, 3 Winsocks, and two textboxes, and 1 command button.
I am trying to send messages to my own machine...

WINSOCKS:
(for sending)
Name: Send
LocalPort: 1028

(for listening)
Name: Listen
LocaPort: 1029

Name of my PC on network: Nil

CODE:

On form load, I invoked the listener to listen:
Listen.LocalPort = 1029
Listen.Listen

On a command button:
Send.LocalPort=1028
Send.Connect "Nil",1029

(I hope I need not explain this further... the application works fine...)
HOWEVER, when I disconnect (Send.Close), of course it disconnects... BUT when I try to connect again on the same localport:
Send.LocalPort = 1028
Send.Connect "Nil",1029
(This is the same as the code above...)

The damn thing cant connect. ERROR: Port in use!!! :(
I hate to use another port. Is there a way to work around this? HOWEVER, after sometime, the port is free again!!! (I hate to wait too)

I want a clean close, not just the close method. I think the close method does not free the port. The damn thing thinks the port is still in use after I invoke the Close Method.

So I guess, my question is, is there a way to free a port? And, Why on earth is this happening?? (I know the basics of TCP/IP with Winsock... I just need to know the basics of PORTS... hehe...)

I have scrambled over tons of crap explanations but nothing tells me how to work around this... Nothing tells me something about a 'Neat' disconnect.

Any advice on this, please? Any help would be very much appreciated. :)

Thanks.
Jonaxse


[Edited by jonaxse on 11-02-2000 at 02:15 AM]

Nov 2nd, 2000, 01:23 AM
You don't need to set a LocalPort for your server, all you need to do is:

Server

Listen.LocalPort = 1028
Listen.Listen


Client

Send.RemotePort = 1028
Send.RemoteHost = ServerName
Send.Connect


But to answer you question, by doing it this way, when on side of the connection is closed, the other side will close and the port used will close. Not needing you to finish off other things yourself.

Sunny


[Edited by sunnyl on 11-02-2000 at 02:26 AM]

jonaxse
Nov 2nd, 2000, 07:35 AM
I did not realize... Hmm...
When the client connects, I dont need to set the localport? Is that what u are saying?

Well, if the way I understand it, you are saying that I do NOT need a localport for the client... the client just needs a remoteport and remotehost, to connect.

When a winsock client connects to a remote port and you do not provide a localport for the client, does the client generate a random port number to use for that?


Anyway, Thanks for the suggestion, Im gonna try it.
Yer help is very much appreciated.
:) Jonn

Nov 3rd, 2000, 05:47 AM
You may be getting the wrong impression that each port is only a one way communication pathway, however this isn't the case. Each port can send/receive, it is simply a matter of pointing the client to the port that the server is listening to. For example, HTTP flows through port 80, but of course, communication with a browser and web server is a two way communication, yet it is all done through port 80.

From MSDN:
If you are creating a client application, you must know the server computer's name or IP address (RemoteHost property), as well as the port (RemotePort property) on which it will be "listening." Then invoke the Connect method.

If you are creating a server application, set a port (LocalPort property) on which to listen, and invoke the Listen method. When the client computer requests a connection, the ConnectionRequest event will occur. To complete the connection, invoke the Accept method within the ConnectionRequest event.


Sunny

jonaxse
Nov 3rd, 2000, 06:37 AM
Thanks for the reply... I think I found the problem.
Problem (I think): When the client connects to the server, the server designates another winsock control to accept the request ID (perhaps on a control array)...
But when the client disconnects thru the .Close method, the winsock on the server didnt know about it (am I right?)... so It still maintains the connection thru that port, regardless of the client's status (I think this is where timeouts get useful). So when I try to reconnect on the same port, it says "Port is being used.".... Simply because I only invoked the .Close method on the client (does the server have to close the IP connection too?)

This is my solution: (please give me some advice on whether this is the best solution there is...)
On the Client side, before i disconnect, I send a message (i.e. "/Close" <--- this is just some sort of my own protocol... :)) When the server receives this message, it sends back a confirmation..(i.e. "/CloseGoAhead") then the server terminates the connection on its side thru the .Close method. When the client receives the message, (i.e. "/CloseGoAhead") it closes its connection too (.Close)... So now, the port is free!!! (I think)

So when I connect back an instant later, It works !!!:)
I think the protocol thing is a good one! But what happens is when the connection is terminated by something else... Maybe this is where timeouts get handy.

I just wanna know if it is recommended or would you call it a good practice for a client to periodically send messages to the server, notifying it that the client is still connected? (much like a PING)... it the client does not send any more messages for a specified time, the server automatically closes the connection...(Hmmm.. this is like the IRC...hehe) :)

Thanks for the advice... I now invoke the .Connect method on the client without specifying a localport. I guess the client randomly chooses an available port if u dont specify one (or does it?)

Anyway, what you told me was very helpful. :)

for lCtr = 1 to 1000000
Me.Say "Thanks a lot!"
next lCtr

You.NiceGuy = True
Me.Idiot = True 'I hope not...

:) Jonn

Nov 3rd, 2000, 09:28 PM
Ahh...I'm sorry, I didn't quite read the question all that clearly the first time round. But I now understand your problem more clearly.

After you invoked Close, you couldn't reconnect. The problem and solution is simple.

When you have connected, you are at state 7 (connected), after invoking Close on the client it will goto state 0 (closed). However, on the server side (or the side that didn't invoke the Close method) will goto state 8 (peer closing connection) for sometime before it goes back to state 0 (closed). So when you tried to reconnect to it when it is still listening/closing an error occurs.

To solve this, after you know the last transaction has occurred (see below), you should restart the listening process in the listener with something like:


Public Sub RestartConnection()
wskListen.Close
wskListen.LocalPort = 1000
wskListen.Listen
End Sub


To know when to reinvoke the Listen method on the server, the client should attach a little string to the end of its last message, and when the server parses the received string and sees that particular string, it will close on its own.

For example,

Private Sub cmdClose_Click()
wskClient.SendData YourMessage & "|Close|"
LastMessage = True
End Sub

Private Sub wskClient_SendComplete()
If LastMessage = True Then
wskClient.Close
LastMessage = False
End If
End Sub


and on the server end:


Private Sub wskListen_DataArrival(ByVal bytesTotal As Long)
Dim str As String

wskListen.GetData str

If Right(str, 6) = "|Close|" Then
Call RestartConnection
End If
End Sub

Public Sub RestartConnection()
wskListen.Close
wskListen.LocalPort = 1000
wskListen.Listen
End Sub


This code will get the server to start listening again as soon as a 'finished' mark is received.


I guess the client randomly chooses an available port if u dont specify one (or does it?)


Yes, it picks a random port.

Sunny

[Edited by sunnyl on 11-03-2000 at 10:32 PM]

jonaxse
Nov 3rd, 2000, 11:57 PM
Thanks so much...
Your words of wisdom cleared things up...

=====================
1.> Client chooses a random port on connect.
2.> Both sides has to close the connection or the server does a timeout (its gonna take long)
3.> The protocol is important...hehe
4.> Im happy. :)

Thanks.

Ur help had been most invaluable.