An advanced multiple client server chat program using Winsock control

Level:
Level3

If you haven't read the first tutorial (A Client server Chat program using Winsock control tutorial) - please do so now. This VB6 tutorial builds off of the previous one. This tutorial differs from the first one in that you can have more than one client connect at a time. This is similar to how IRC works.

We will not need to change anything in the client portion of our program. It behaves in the exact same way. However, in the server side of our program we have to get a little creative. If you remember in the last tutorial we simply disconnected any pervious connects and accepted the new connection in the Winsock controls ConnectionRequest event. Now instead of doing this we will allow multiple connections to occur. To handle that we will be creating a control array of Winsock controls. Then when a connection comes in on our main socket we will create a new Winsock control in our control array and assign the connection to it. If this sounds confusing just follow along and it will make much more sense. First set the index property of sockMain on Form2 to 0. This tells VB6 that sockMain is now a control array. This will allow us to create more controls at runtime.

Also download the source code if you want to follow along with this tutorial.

To begin open up Form2's code window. We will be adding a global variable that will keep track of the number of connections we have.

Option Explicit
Private intSockCnt As Integer
Next delete any of our old code we will be recreating it. Now lets start with the tricky part first - sockMains connectionRequest event. If you notice the sockMain_ConnectionRequest now has two parameters instead of one. The new parameter index. This index value will tell us what sockMain in our array of sockets had a connection request. Add this code in this event.
Private Sub sockMain_ConnectionRequest(Index As Integer, _
   ByVal requestID As Long)
   
   intSockCnt = intSockCnt + 1
   
   Load sockMain(intSockCnt)
   sockMain(intSockCnt).Accept requestID
    
   txtStatus.Text = txtStatus.Text & _
      "Connected to: " & _
      sockMain(intSockCnt).RemoteHostIP & vbCrLf
End Sub

This code is similar to what we did in our last tutorial. However, instead of simply accepting the connection and killing any old ones, we load a new Winsock control and accept the connection on that one instead. This is where the requestID comes in handy. Because when we load our new Winsock control it doesn't know anything about the connection attempt made to our old control. However, when we call the Accept method on our new control and pass it this requestID it will take over the rest of the processing from that client.

Now lets write the code to handle data arriving.

 

Private Sub sockMain_DataArrival(Index As Integer, _
   ByVal bytesTotal As Long)
    
   Dim strData As String
   Dim intCnt As Integer
    
   sockMain(Index).GetData strData, vbString
   txtStatus.Text = txtStatus.Text & _
      strData & vbCrLf
   
   'This sends the data back to the other clients
   For intCnt = 1 To intSockCnt
      If sockMain(Index).State = sckConnected Then
         sockMain(Index).SendData strData
      End If
   Next intCnt
End Sub

Again notice we have the handy index property and again notice our code is very similar to the previous tutorials code. The only difference is that we use the index variable and we resend the data back out to any other clients that are connected. We do this with the For loop. We loop through our array of connections. If they are still connected then we send them the data.

Next lets wire up our Listen and send command buttons.

Private Sub cmdListen_Click()
   sockMain(0).Close
   sockMain(0).LocalPort = txtPort.Text
   sockMain(0).Listen
End Sub
   
Private Sub cmdSend_Click()
   Dim intCnt As Integer
    
   'This sends the data back to the other clients
   For intCnt = 1 To intSockCnt
      If sockMain(intCnt).State = sckConnected Then
         sockMain(intCnt).SendData txtSend.Text
      End If
   Next intCnt
End Sub

This is almost exactly like our last tutorial. The only difference in cmdListen_Click is that we are specifing our array index of 0 in our listen event - this is the main socket control we created on Form2. The other difference in our cmdSend_Click is that we loop through all our open connections and send the data to them.

It is a bit tricky to test this out as we need two clients. I recommend compiling the program as an exe. Than you can run it more than once. Just remember to only have one server (form2) listening at a time - than you can have as many clients (form1) as you want connect to them.

There you have it. Now to make this a working program you will want to add some better error handling, but you get the idea from this tutorial. Also download the source code for this tutorial to see a working example.

If you enjoyed this post, subscribe for updates (it's free)

help!

the tutorial is great...
big thanks to you...
i just want to ask.
if i am the server, how can i view my message?
coz only clients can view mine...
is it possible to view it?
sory for my english...
thank u...

help

How should connect the single client to Multiple server,Multiple Server access the same client.
using Winsock Control in Visual Basic............

sckClosed and sockMain.State are having errors

when i implemented the winsock connection request, it gave me error messages;
"'state' is a type in ' AxMSWinsockLib.Axwinsock and cannot be used as an expression" and
"'sckclosed' is not declared" what type of variable is this going to have.
I am using vb2008. Thanks

scheduling task from multiple clients with a timer in VB6

hi
i need code for scheduler which starts the timer when multiple clients sends a request to server to perform a particular task in VB6 socket programming. pls help me out ASAP.. thanks in advance.

error in loop

'This sends the data back to the other clients
For intCnt = 1 To intSockCnt
If sockMain(Index).State = sckConnected Then sockMain(Index).SendData strData
doevents
Next intCnt

you forgot the doevents

'doevents'

'doevents' means it's up to you on what the program should do on that line.

i have got this and i have

i have got this and i have been messing with it and i was wondering if you was about to code into it where people could use and username they pick

where they have to input a username before it connects to the server

and the other thing i was wondering about are you able to take say a listbox and be able to show the list of users that is connected to the server

Reaper

SOLUTION!

Okay everybody listen up. There is three simple reasons you are having trouble with this.

The first step is to look at your designer, select the winsock control (sockMain). Set the index property of sockMain to 0. That's a zero.

The second step is to add "Index As Integer" to the beginning of all your functions that have to deal with sockMain

For example:

Private Sub sockMain_ConnectionRequest(ByVal requestID As Long)
The connection request sub function above normally looks like that. You must change it so it now looks like this:

Private Sub sockMain_ConnectionRequest(Index As Integer, ByVal requestID As Long)

Notice the difference between them after ConnectionRequest.
That should be applied to sockMain_ConnectionRequest and sockMain_DataArrival.

Next, in the connection request function, where is says sockMain.RemoteHostIP. Change that to sockMain(intSockCnt).RemoteHostIP.
That lets the program know which index of the sockMain to pull the IP from.

txtStatus.Text = txtStatus.Text & "Accepted Request from: " & sockMain(intSockCnt).RemoteHostIP & vbCrLf

Lastly, in the same function as before (connectionrequest), change Load sockMain(intSockCnt + 1) to:

Load sockMain(intSockCnt)

If you have any further problems download the source code from the author of this tutorial and check the differences between your program and that one.
http://www.vb6.us/files/File/MultiClientServer.zip

If you are still having problems, feel free to email me @ chrism257@gmail.com

Connecting of the Internet

Hello,

Great tutorial! I have this working great over a LAN, but I can't seem to get it to work over the internet. I have a computer that's external and has a static IP, and I can host pages. But I get an error 40006 when I try to connect over the net. Any tips...because this is how I intend to use it...on a server box that's always connected on a static IP address. Other clients will connect into it.

Thanks!!!

Forwarding Ports

The problem with this is that you have a router, I'm guessing, and you didn't forward the ports on the router.

The server side of the program uses a port to listen on. The port is "always" open on your own computer because the server and client are on the same network. But, for another computer to connect to the server, that isn't on the same network, through that port, would require the port to be forwarded, or "open." The best website to learn how to port forward your router is: http://portforward.com/

Email me if you have any further questions @ chrism257@gmail.com

goooooooooooooooooood

goooooooooooooooooood

Bug Fix

Before reading the above comments I noticed the server would only send data to the most recent connection, then when another client connected the data was sent to everyone else. This can be fixed by DoEvents as above, but before I discovered this my way to solve the problem was:
Load sock1(intSockCnt + 1)
Unload sock1(intSockCnt + 1)
I put this after "sending" the data from the server.
DoEvents is better but this may help your understanding of the program a little more!

how to download /get data

how to download /get data file form server by request client

This code sucks i advise you

This code sucks i advise you just add an invisible text box and when someone chats it adds to it ok and have a timer every 2 seconds it sends the text to the clients .

NOT WORKING

Sir, have you tried using your application? because its the same way my application behaves. Let us put it this way, client1 request connection to the server, server granted at winsock object index 1, another, client2 at index 3. If client1 sends data to server the server then will use looping to send the data to all clients, now here's the problem, when the loop starts it will first send data to client1 and client2 , only client2 will receive the data... I am now working with a chat program with a database and it works fine , the user can log-in and out but the only problem I have is that I cannot send data to multiple client... I tried putting a delay on the loop, a message box (msgbox "sent") so that everytime the loop counts a message box will appear, it works, all clients receive data. What do you think is the problem?

ER: Procedure declaration

If u have an error about

Procedure declaration does not math description of event or procedure having the same name

Just put a INDEX 0 in the server winsock property

how ?

how ?

hi, is this posible or

hi, is this posible or applicable if i want to use my customer file to be share by branches?

Get data

please tell me, how to get multi data from client
ex:
I have 2 value and want to sent to server process and return a result

This will not work correctly

This will not work correctly for all clients, the data may not be sent to all connected clients:

If sockMain(Index).State = sckConnected Then
sockMain(Index).SendData strData
End If

Just add a call to DoEvents:

If sockMain(Index).State = sckConnected Then
sockMain(Index).SendData strData
DoEvents
End If

thank the author thank you

thank the author
thank you for point out this bug. it also save much time for me....
many thanks

Thank you

I would like to thank the author for publishing this and the first valuable tutorials. Sometimes you would read so many books and articals and still couldn't find the answer you want. And yet, thanks to people like the arthur to come up with simple, practical and useful tutorials and examples, they really save me heaps of time and I learnt a lot from them. A big thank you.
I also like to thank this Anonymous person who pointed out a little bug in the code that it would not send message to all clients. The addition of DoEvents statement fixes the problem. You know how much time it saved me? And, a big thank you to this Anonymous person.

Need Help

I get a compile error: Wrong number of arguments or property assignment for the cmdListen_Click event

Private Sub cmdListen_Click()
SockMain(0).Close
SockMain(0).LocalPort = txtPort.Text
SockMain(0).Listen
End Sub

argh

i fixed that by setting the first winsock control index to 0 but now i get another error

run time error "380" invalid property value and it highlights the following

sockMain(0).LocalPort = txtPort.Text

resolved, was because i was

resolved, was because i was using an unknown port =(, but if more than one client is connected the server sends the message to itself multiple times

Server

i was wondering if you could tell me how to run the server on the internet so that it is allways active?

use no-ip.. setup no-ip

use no-ip.. setup no-ip account and use your server name as your ip, if you dont have a static ip then use this

plz help

Can you plz help me when i go to debug it keeps saying "Procedure declaration does not match definition of event or procedure with the same name" and highlights this Sub

Private Sub sockMain_ConnectionRequest(Index As Integer, ByVal requestID As Long)
    intSockCnt = intSockCnt + 1
 
    Load sockMain(intSockCnt)
    sockMain(intSockCnt).Accept requestID
 
    txtStatus.Text = txtStatus.Text & _
        "Connected to: " & _
        sockMain(intSockCnt).RemoteHostIP & vbCrLf
End Sub
<code>
 
//NVM i fixed it i forgot to change the sockMain.index property to 0\\

Help

For some reason when i go to debug it keeps saying "Procedure declaration does not math description of event or procedure having the same name" and highlights this Sub
Private Sub sockMain_ConnectionRequest(Index As Integer, ByVal requestID As Long)
intSockCnt = intSockCnt + 1

Load sockMain(intSockCnt)
sockMain(intSockCnt).Accept requestID

txtStatus.Text = txtStatus.Text & _
"Connected to: " & _
sockMain(intSockCnt).RemoteHostIP & vbCrLf
End Sub

><

This doesnt send data to the other client. Only the server. How can i fix this?
fixed it.
These are great please make more network tutorials!

doesnt send data to the other client

There is a bug in the code of sub sockMain_DataArrival(..)
change from
13. If sockMain(index).State = sckConnected Then
14. sockMain(index).SendData strData
15. End If
to
13. If sockMain(intCnt).State = sckConnected Then
14. sockMain(intCnt).SendData strData
15. End If