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.
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.
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.
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.
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!®©
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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
Thanks
ASKER
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
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
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
ASKER
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!®©
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
C
--------------------------
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.