Solved

Winsock Control - Multi-connections

Posted on 1997-09-16
6
628 Views
Last Modified: 2013-11-13
Hi,
  I have used the following server code successfully to establish a connection with a client program and receive data from the client.  I took the code right out of the Books Online TCP server example and made just a couple minor modifications.  This is what I have...

Private Sub Form_Load()
    ' Set the LocalPort property to an integer.
    ' Then invoke the Listen method.
    tcpServer.LocalPort = 2345
    tcpServer.Listen
End Sub

Private Sub tcpServer_ConnectionRequest _
(ByVal requestID As Long)
    ' Check if the control's State is closed. If not,
    ' close the connection before accepting the new
    ' connection.
    If tcpServer.State <> sckClosed Then _
    tcpServer.Close
    ' Accept the request with the requestID
    ' parameter.
    tcpServer.Accept requestID
End Sub

Private Sub txtSendData_Change()
    ' The TextBox control named txtSendData
    ' contains the data to be sent. Whenever the user
    ' types into the  textbox, the  string is sent
    ' using the SendData method.
    tcpServer.SendData txtSendData.Text
End Sub

Private Sub tcpServer_DataArrival _
(ByVal bytesTotal As Long)
    ' Declare a variable for the incoming data.
    ' Invoke the GetData method and set the Text
    ' property of a TextBox named txtOutput to
    ' the data.
    Dim strData As String
    tcpServer.GetData strData
    txtOutput.Text = strData
End Sub

What I want to do is allow multiple connections.  Books Online gives this code to achieve that purpose...

Private intMax As Long

Private Sub Form_Load()
      intMax = 0
      sckServer(0).LocalPort = 1001
      sckServer(0).Listen
End Sub

Private Sub sckServer_ConnectionRequest _
(Index As Integer, ByVal requestID As Long)
      If Index = 0 Then
            intMax = intMax + 1
            Load sckServer(intMax)
            sckServer(intMax).LocalPort = 0
            sckServer(intMax).Accept requestID
            Load txtData(intMax)
      End If
End Sub

Being such a beginner, I don't fully understand this latter part and was wondering if anyone could put the 2 pieces of code together for me to make it work for accepting multiple connections.  I'm having a tough time visualizing what would happen when a subsequent connection request is made since this latter code only addresses the possibility of Index = 0, and does not have an 'else if' or an 'else' attached to the 'sckServer_ConnectionRequest' routine.  Thanks in advance
Paul
0
Comment
Question by:zingbust
  • 5
6 Comments
 
LVL 5

Accepted Solution

by:
volking earned 200 total points
ID: 1435155
Wow, where do I begin ...
Give me 20-30 minutes and I'll work up an answer and post it here. Don't grade me until I've posted my next submission

============> Frederick Volking
0
 
LVL 5

Expert Comment

by:volking
ID: 1435156
First let me applaude your effort. The approach you’re taking is wonderful. Find some code that does "almost" what you want and learn enough to change it. That’s an absolutely wonderful way to learn!

Okay let’s start with the basics (no pun intended)

DIM  X AS INTEGER

We have ONE instance of a variable called X

DIM X(75) AS INTEGER

We have SEVENTY-SIX instances of a variable called X (76 because arrays start at 0 so 1 to 75 = 75 plus 0 = 76)

TYPE MYSTRUC
X AS INTEGER
Y AS LONG
Z AS STRING
END TYPE

DIM ABC(50) AS MYSTRUC

We have FIFTY instances of a structure called ABC and the structure ABC is composed of a type called MYSTRUC, therefore . . .
We have FIFTY instances of a variable called X
We have FIFTY instances of a variable called Y
We have FIFTY instances of a variable called Z

To address individual variables we first identify which one of the FIFTY possible structures we’re referencing, then we identify which component of the structure MYSTRUC we actually want

Example:
ABC(20).X = 99
ABC(50).Z = "Hello"

Hopefully these concepts are familiar to you. This may be over simplistic but I’m not sure of your skill level so I’m starting at ground zero.

Now that I’ve laid that foundation, let’s look at your code.

What you’re dealing with is a "control" which has been named tcpServer. To make visualization easier, let’s imagine that the control tcpServer is really nothing more than a fancy structure. To make multiple instances of a structure you DIMension the structure to a predetermined quantity. If the tcpServer control was a structure made up from several variables, it might look something like this . . .

Type WinSock
          LocalPort as long
          Protocol as string
          State as boolean
          RemoteHost as string
          RemotePort as long
end type
DIM tcpServer(10) as WinSock

If  WinSock was a structure, then the above line would give us 11 instances of the WinSock structure. (Remember, the WinSock control is NOT really a structure but to visualize it this way may help you understand how to handle multiple instances of a control).

Since the WinSock control is not a structure, instead of DIMing 10 instances, we add 10 individual WinSock controls to our form! Make sure to name all 10 controls exactly the same name but set their INDEX to 0, 1, 2, 3, etc . . .

When you’re done, you’ll have 10 instances of the WinSock control, which can be addressed and manipulated as individuals.

And to address any one of them, you’ll need to first identify which (of the ten) you want then then set the property.

Also when an event fires, you’ll need to know which control fired . . . so let’s rewrite your code segments.

Remember, the below code assumes you have 10 copies of the WinSock control on your form and they’re all named WinSock and their Indexes are numbered 1 to 10.

Private Sub Form_Load()
for count% = 1 to 10
WinSock(count%).LocalPort = 2344 + Count%
WinSock(count%).Listen
next
End Sub

Private Sub WinSock_ConnectionRequest (Index as integer, ByVal requestID As Long)
If WinSock(Index).State <> sckClosed Then WinSock(Index).Close
WinSock(Index).Accept requestID
End Sub

Private Sub txtSendData_Change()
 ‘remember, we’ve got 10 incidents of the WinSock control, to send data out one of them we must FIRST decide which one to use, so I’ve simulated that we have a variable set to determine which WinSock to use
WinSock(WhichWinSock).SendData txtSendData.Text
End Sub

Private Sub WinSock_DataArrival (Index as integer, ByVal bytesTotal As Long)
WinSock(Index).GetData txtOutput.Text
End Sub

-------------------------------------
The code above here assumes that you have 10 copies of the WinSock control ALREADY on the form. But the code below here is very different . . . and VERY TRICKY.

VB has the ability to create new instances of a control ON-THE-FLY! Instantly! Like Magic! All you need is one copy of the control and you can instruct VB to suddenly create additional copies. This "magic" is done with the LOAD command. Using the Load command in this way is really quite advanced and has several critical limitation and a few real headaches! (such as how to get rid of the controls once you create them because they must be destroyed in the EXACT REVERSE ORDER they were created!) But if you really want to try this method, I’ll try to explain it . . .

Let’s assume your form has one WinSock control called WinSock. Every time that control recieves a ConnectionRequest we’re going to
A) Make a new copy of the existing WinSock control, then
B) Attach the incoming request to the NEWLY CREATED control (NOT the existing control)

First step is to keep track of how many controls we’ve created up until this particular moment in time. So we create a variable with a scope of Module level to track how many instances we have.

Private intMax As Long

Next, when the request come in, . . . .

Private Sub WinSock_ConnectionRequest (Index As Integer, ByVal requestID As Long)
‘first let’s make sure the request is coming from the first instance of the control
If Index = 0 Then
‘yes, it’s coming from the first instance so we increment the count of how many controls we have all together
intMax = intMax + 1
‘then we magically create another instance and assign it’s position to the highest instance
Load WinSock(intMax)
‘then we set it’s local port and tell it to talk to the incoming request
WinSock(intMax).LocalPort = 0
WinSock(intMax).Accept requestID
‘Im not sure what this next line is for . . . except possibly to allow a location to put the incoming text, so we magically create another instance of the TextBox and also assign it’s position to the highest instance
Load txtData(intMax)
End If
End Sub

-------------------------------------

Okay, that’s what’s happening. But let me warn you, using the LOAD command to magically create additional instances of controls is very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very TRICKY !

There are lots of  problems and it takes a real professional to make it work. I’ve been coding for about 25 years and it’s a task I would not attempt if there was any other approach.

Using the first approach, where you pre-make 10 instances of the control, is a far more "friendly" method, but of course has limitation.

The approach you finally take is your decision. I wish you luck.

Keep going!

============> Frederick Volking


0
 
LVL 5

Expert Comment

by:volking
ID: 1435157
BTW ... You can reach me directly at

volking@visa.com

========> Frederick Volking
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 5

Expert Comment

by:volking
ID: 1435158
Sorry that's a typo - the correct address is

fvolking@visa.com

It's getting late .... I'm hungry ... good night!



0
 

Author Comment

by:zingbust
ID: 1435159
Thanks for spending so much time with this.  My skill level is spotty, so the primer was much appreciated.  I'm not sure how I should approach this because what I'm going to be doing is having a continuous flow of connection requests from my web-site (where the client program resides).  Once the system is up and running, it must run automatically.  I had visualized using the control array to save on memory, but you say the controls have to be destroyed in reverse order from the way they were created, which won't work because at any given time, there may be a number of simultaneous connections that are active.  Surely there must be a way to destroy them as soon as the connections are closed, isn't there?!?!  By the way, by changing my code to reflect the changes you advised, the server program is now able to take multiple requests, however the data does not get displayed in the text box, but that's not important, because this is only a test, anyway.  The real application will be writing the data to a file where it can be opened and acted upon by another part of the total program.  
0
 
LVL 5

Expert Comment

by:volking
ID: 1435160
One approach I've seen work is to establish a limited pool of resources and maintain a set of flags about which connections are in use and which are free. Then, when new connection requests are recieved, scan through the pool looking for a free connection. Also, you might want one "special" connection that is never used except when the pool is used-up. Do a quick connection to the "special" control, dump a message like "Server Too Busy" and force a connection terminate.

Have fun
=============> Frederick Volking
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Windows Script Host (WSH) has been part of Windows since Windows NT4. Windows Script Host provides architecture for building dynamic scripts that consist of a core object model, scripting hosts, and scripting engines. The key components of Window…
When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now