Link to home
Start Free TrialLog in
Avatar of JohnRock
JohnRock

asked on

multiple clients

I have an application that needs multiple clients connecting to a server.

On the server side I create a new winsock control for each new client.

When the server is requested something by a client it passes the request off to a Receive object. A new instance of this object is created each time a connection is made.

This does not seem to work. If I have two clients and one of the clients has requested something, and another client has requested something else, the server stops interacting with the first client, but carries on with the second request.
Avatar of wsh2
wsh2

As your question is not entirely clear.. (what type COM component this is.. what Model Threading you are using).. let me take a stab that perhaps it is a Rentrancy problem.. From MSDN:

------------------------------------
Reentrancy

In the apartment model, reentrancy refers to the following sequence of events:

An apartment’s thread of execution enters an object’s code, because a property or method has been invoked.

While the thread is in the property or method, another thread invokes a property or method of the object, and Automation serializes this request — that is, it queues the request until the thread that owns the object’s apartment finishes the member it’s currently executing.

Before the thread reaches the end of the member, it executes code that yields control of the processor.

Automation tells the thread to begin executing the serialized request, so that the thread reenters the object’s code.

The new request may be for the member the thread was already executing — in which case the thread enters the member a second time — or it may be for another member. If the second member doesn’t yield, it will finish processing before the first member. If it changes module-level data the first member was using, the result may be unfortunate.

By serializing property and method calls for each apartment, Automation protects you from reentrancy — unless your code yields control of the processor. Ways in which your code can yield control of the processor include:

1.  Calling DoEvents.

2.  Invoking the properties or methods of an object on another thread, or in another process.

3.  Raising an event that’s handled by an object on another thread, or in another process.

4.  Invoking a cross-thread or cross-process method from within a method.

5.  Showing a form.
 
Unless you’ve carefully written all of an object’s code so that it doesn’t matter whether two members are executing at the same time, you should not include code that yields control of the processor.
JohnRock.
Just a simple comment. Did you use different local port numbers for the new winsocks created on the server side. If you didn't this may be your problem.
If I am right and you don't know how to solve it please reply.

Regards,
C.
Avatar of JohnRock

ASKER

When ever I create a new connection with the server I set the server's local port to 0.
You could try doing a "DoEvents" after your SendData and GetData calls.  It may help.  Also see the following microsoft KB article:

BUG: Winsock Control SendData Only Works Over the Latest Connection
http://support.microsoft.com/support/kb/articles/Q245/1/59.ASP?LNG=ENG&SA=MSDN&FR=0 
 

Cheers!®©

ASKER CERTIFIED SOLUTION
Avatar of cgallagher
cgallagher

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I'll give it a try. I think if you set the locol port on the server side to 0 it randomly selects a local port for your client winsock to connect.

Thanks
Please can you send me some sample code to do this.
I have it done in C++ so it will take me a while or so to program it in visual basic. Give me an hour and I'll get back to you.
Ok. I was looking at the bugs in winsock that the above people were on about. There is a bug - the data is not flushed out of the socket until you leave the function.
In a round about way I got around the problem. I used a timer to send the data to all the clients instead of looping through all the sockets and sending to them.

I persume you used the MSDN example to base your program on. Here is the modified code off the MSDN.

SERVER CODE:-

Dim x As Long
Dim st As String


Private Sub Form_Load()
x = 2001
    Ws.LocalPort = 2000
    Ws.Listen
   
End Sub

Private Sub Timer1_Timer()
Static i As Integer
    If i + 2002 > x Then
        Timer1.Interval = 0
        i = 0
        Exit Sub
    End If
    i = i + 1
    W(i).SendData (st)
   
End Sub

Private Sub W_ConnectionRequest(Index As Integer, ByVal requestID As Long)
    W(Index).Close
    W(Index).Accept requestID

End Sub

Private Sub W_DataArrival(Index As Integer, ByVal bytesTotal As Long)
W(Index).GetData st
Text1.Text = st
Timer1.Interval = 1
End Sub

Private Sub Ws_Close()
    Ws.Close
    Ws.Listen

End Sub

Private Sub Ws_ConnectionRequest(ByVal requestID As Long)
    x = x + 1
    Ws.Close
    Ws.Accept requestID
    Load W(x - 2001)
    W(x - 2001).LocalPort = x
    W(x - 2001).Listen
    st = CStr(x)
    Ws.SendData (st)

End Sub






CLIENT CODE:-

Dim cced As Boolean

Private Sub Command1_Click()
 W.SendData Text1.Text
 
End Sub

Private Sub Form_Load()
W.RemoteHost = "bscc9906-2"
W.RemotePort = 2000
W.Connect

End Sub

Private Sub W_Connect()
    Text1 = "CONNECTED"
End Sub

Private Sub W_DataArrival(ByVal bytesTotal As Long)
Dim str As String
    W.GetData str
    If cced Then
        Text1.Text = str
    Else
        W.Close
        x = CInt(str)
        W.RemoteHost = "bscc9906-2"
        W.RemotePort = x
        W.Connect
        cced = True
    End If
   
End Sub



I was actually incorrect in accepting my answer. The correct answer was setting the Doevents after the getdata and senddata methods. Thanks for the help.
JohnRock,

If you accepted the wrong answer, please open a question in the Customer Service category so that the correct answer can get the points...  


Cheers!®©
You can unaccept my answer if you want. I dont mind. Their answer was actually correct.
C