Winsock Help needed....... (Part 1)

Hi all,
I am developing a system in which I will have a central server....... There will be some clients (at the maximum 10)..
These clients will connect to the Server and will get updated..... The updation is simply the updation of a text file that is present both at the Server and Client (Server will alway have the most updated text file).....I decided to use a Winsock Control for the Data Transfer and the Server-Client will communicate with the following sequence........

Server Client

<------------------------------Establish a Connection--------------------

<----------------------------(Update Me)

(Ready to Send File)------------------------->

<----------------------------( I have x Lines/Bytes) (So that only changes are transmitted)

(Ok) ------------------------------------------>

("###") --------------------------------------> (Tells to the client start of sending Data)

(Data)----------------------------------------> (Actual Data to be send)

("***") ---------------------------------------> (Tells the client End of sending Data)

<------------------------------( I have Received x Lines/Bytes)

(Ok) ---------------------------------------->

<---------------------------End Connection-------------------->

I have done some coding for this but I am stuck in some points.........So I want you people to help me out in this problem...
and let me tell u I am almost a novice as the Network Programming (Winsock Control ) is concerned

Connection Establishment......

I think that at the client side the connection establishment is very simple.......
Here is some of my code......

Private Sub Form_Load()

WskClient.Connect "LocalHost", 1001
If Err <> 0 Then
WskClient.Close
End If
WskClient.SendData "Msg_Update"

Since I donot know much about Winsock so here are a few questions that are stuck into my mind......

1) As the code illustrates that WskServer(0) is always in listening mode and whenever a new Request arrives it simply creates a new instance of of WskServer which accepts the connection.......So if my Server is running 24hrs/ 7 days then intMax=intMax+1 will cause the intMax value to be out of bounds of Long within a couple of Weeks.....How to avoid that?

2) Since I will have fixed no. of Clients that can communicate with my Server say only 3 then do I need to use it in this way that I have shown in the example?
How can I use it like this "if Client1 connects with me then Load WskServer(1) similarly for Client2 load WskServer (2) and when it disConnects UnLoad its respective Control i.e like Unload WskServer(1) after Client 1 is being updated completely.....

3) How do the Server knows that Client1 is still connected with me ?

4) How do the Client1 knows that it is still connected with the Server ?

Note:::::

This is the first Part of this series of Questions almost all of which will be focussing around Winsock.......

1) for the first question you can look at this example: http://www.winsockvb.com/article.php?article_id=19
2) it is best to use the method that you are currently using
3) and 4) Winsock is maintaining the connection so it assumes they are connected until one of them disconnects --> Winsock_ConnectionClosed event

Below is a basic server that can handle multiple clients and recycle unused winsock controls.

The biggest problem I see however is in your handling of the incoming stream in the DataArrival() Event. In a perfect world you will receive the packets exactly as they were sent. In the real world though, packets often get chopped up along the way. For instance, if you send "This is a message" from the client, it may actually arrive at the server as two different DataArrival() events; one with "This is a me" and the other with "ssage". There is no way to prevent this and it is not seen as a bug. The TCP protocol simply states that the information you send will arrive in the order you sent it, but not neccessarily in the chunk size you sent it. Along the same lines, if you send two different messages, "Cats" and "Dogs", they may arrive as one message appended together as "CatsDogs". It is also unsafe to use the same buffer for all clients since you may get part of a message from one client and then immediately receive part of a message from another client.

To get around these problems you need to mark the end of your message with some kind of control character, or sequence of characters, and keep seperate stream buffers for each client. Furthermore, you must store your incoming stream in a persistent buffer so that you can append the current stream data to what has arrived before. In this manner, you can correctly handle a message that has been split into mulitple pieces. In your implementation you declared RecBuffer as a local variable in the DataArrival() event. If a message arrives in pieces, the previous portions will be lost.

In the example below I have used Chr(1) as an End of Message marker and Chr(0) as a parameter delimiter. For instance, you could send:

' See if there is an available Channel already loaded
acceptIndex = -1
If index = 0 Then
For curindex = 1 To Winsock1.UBound
If Winsock1(curindex).State = sckClosed Then
acceptIndex = curindex
Exit For
End If
Next curindex
End If

' see if we have a msg in our buffer
markerPos = InStr(inputBuffer(index), Chr(1))
Do While markerPos > 0 ' if we have a msg then process it
curInput = Left$(inputBuffer(index), markerPos - 1) ' get msg from buffer
inputBuffer(index) = Mid(inputBuffer(index), markerPos + 1) ' remove msg from buffer

Thanks anv and darkoLord for your help......This site contains really good articles even for a novice like me....

Idle_Mind,
Thanks for your help and source code......I have almost got the idea.....Here is what I have got from your Code Please correct me where I am wrong.....

1) WinSock(0) at the server side is always listening and its purpose is only to Listen the Connection Requests from Clietns....

2) WinSock(1) will always be connected to the first Client that is trying to connect....and so on for the remaining Clients....

3) inputBuffer(index) will contain all the Commands/Data that is received from the Client

4) All commands will contain chr(1) as an indication that the command is finished.....and if I am sending multiple commands in one command then it will be separated by chr(0)

So now I have a few questions.....

a) If I want to know which Client is trying to connect to the Server how can I know ?
i.e. if I want to know who is connected onto the server on the socket WinSock(1) ?
Do I need to send some parameters from Client like this
msg = "UpdateInfo" & "Client A" & Chr(0) & numLines & Chr(0) & numBytes & Chr(1)
Winsock_ClientA.SendData msg

so that the Server will know this is "Client A" or is there some direct method of finding who is connected on WinSock(1) ?

b) What I want to achieve is a sequential flow of my program......i.e After connection my Client will send some Command (Message), the Server will (when received that command) follow up with a command to the client and so on.....Like I have shown in my question....

Now as you have said that my Command might be divided into many parts and I might recieve "This is a Message" as "This is a Mess" and "age".....As long as the sequence remains tha same I have no problem as the inputBuffer(index) will contain the complete command "This is a Message" which I can recognise ,decode and acknowledge.....But what happens if I get it in wrong order Like "ageThis is a Mess" How to handle such situations ? Are such situations Possible at all ?

So according to my algo the Server should not acknowledge Client that it has received some Command/Request/Message from Client but in fact it has received......How to tackle this situation as the client will be waiting for a response to the Command it has send?

Once these Queries are answered I will post "Part 2" of this question that will be rotating around Sending Large Text on WinSock.......

a) If clients have static IPs you can use .RemoteHostIP property to get it's IP... otherwise you would have to send some "authentication" data first
b) Received data cannot be messed up, however you could receive multiple commands in one... thats why you should end each command with a nullchar (vbNullChar constand) as you can see in Idle_Mind's example above...

As for sending response that the command has been received, you don't need to do this... My advice is to split your communication to multiple stages and then you can use winsock's .Tag property to know which stage is each client in...

Also it is easy to mark each data with a number... for example: "hello" can be 1, "ok" can be 2 and so on.... you can then use Chr$(Command_ID) so it takes only one byte and you can parse it easily...

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

>>As for sending response that the command has been received, you don't need to do this... My advice is to split your >>communication to multiple stages and then you can use winsock's .Tag property to know which stage is each client in...

Sorry I could not understand this concept.....What I am trying to do is to send some Command from Client and Trigger the next Event (Maybe send next command or send data or close connection) in the Client only after the response from the first command has reached from the Server....Can you supply some source code for what you have suggested ?

>>If clients have static IPs you can use .RemoteHostIP property to get it's IP... otherwise you would have to send >>some "authentication" data first

So the method that I have suggested is good enough to work if I donot have Static IP?
msg = "UpdateInfo" & "Client A" & Chr(0) & numLines & Chr(0) & numBytes & Chr(1)
Winsock_ClientA.SendData msg
I wonder how "Huge Servers" like Kazaa and MSN Messenger work ? Since all of its clients donot have static IP.....Do my Messenger send my Information in the form of above example or do they also send my Dynamic IP with my User Name ?
As far as I know one can check the IP address of whom one is chatting in MSN Messenger......

1) WinSock(0) at the server side is always listening and its purpose is only to Listen the Connection Requests from Clietns....

Correct. (Some people use a completely different Winsock control to always listen)

2) WinSock(1) will always be connected to the first Client that is trying to connect....and so on for the remaining Clients....

Initially the clients will be connected to the same Index number as the order that they connected in. After people disconnect, the winsock control they were using is closed, BUT NOT unloaded. Subsequent connections can then serviced using those already loaded winsock controls. For instance, if you have three clients connect then they would serviced like this:

Index 1 --> Client #1
Index 2 --> Client #2
Index 3 --> Client #3

Then if Client #2 disconnects it will look like this:

Index 1 --> Client #1
Index 2 --> sckClosed
Index 3 --> Client #3

Now when the next client connects they will be serviced using Index 2 since it is available and no new winsock is loaded at this time:

Index 1 --> Client #1
Index 2 --> Client #4
Index 3 --> Client #3

Now if Client #1 and Client #4 disconnect you will have this:

Index 1 --> sckClosed
Index 2 --> sckClosed
Index 3 --> Client #3

Index 1 and Index 2 will not be unloaded because there is still a client connected above them. Unloading them would leave a literal hole in the index array that makes the code nasty since you have to check if the index is instatiated before using it. This requires Error trapping and makes the code harder to read. Once Client #3 disconnects, Index 1, Index 2 and Index 3 will all be unloaded leaving only Index 0 listening for connections.

3) inputBuffer(index) will contain all the Commands/Data that is received from the Client

Correct. DarkoLord suggests using the .Tag property to store each clients stream buffer. Either way will work fine since they are both persistent and not local to the DataArrival() event.

4) All commands will contain chr(1) as an indication that the command is finished.....and if I am sending multiple commands in one command then it will be separated by chr(0)

Yes and no. The way I had coded it, a message is ended with Chr(1). The purpose of Chr(0) was to delimit values for the SAME command so you could easily send related pieces of data like header information for the size of you file. With my code you wouldn't send more than one command seperated by Chr(0), only Chr(1). This is just the way I chose to do it. You need to decide on a protocol that works for your situation and pick delimiters that make sense. In a plain text chat application, Chr(1) and Chr(0) work great. If you are sending binary data, the don't work so great since those characters may actually exist in the stream. In that case you could use longer delimiters that are unlikely to occur in the stream.

a) If I want to know which Client is trying to connect to the Server how can I know ?

As Darko said, unless your clients have Static IPs then they will have to "login" once they connect. This requires a small bit of setup on the client side unless you can install each one with some kind of unique identifier in a data file to use as a login ID. You would just make your own protocol for the login message like (if you have passwords):

You wont get the packets out of order using the TCP protocol. That is possible using the UDP protocol however, which is why you don't see it used very often for file transfers since you have to manage the packets very carefully at a low level and possibly store them until you receive missing packets to fill in the holes.

>>However, are you ABSOLUTELY sure you really need to wait for response??

Yes because some of these might contain data that is going to be used in the subsequent commands.....Like the NoOfBytes or NoOfLines parameter that will tell me what chunk of File I need to send(the unupdated part of file).....

I will come back in about 90 min. and then I will try to Close this question and post the New Question....

>>You wont get the packets out of order using the TCP protocol.
>>The TCP protocol simply states that the information you send will arrive in the order you sent it, but not neccessarily in
>> the chunk size you sent it.

I had missed it in your earlier post......SO this is good news for me.....

Also what will happen if both server and Client are connected but one of them gets disconnected from the internet while protocol \ command interchange is still in progress??
Will the ServerWinsock_Close( ) and ClientWinsock_Close( ) event be fired at both ends ? Since I am currently developing both the Server and Client on the same system I don't know how will it react on the internet.....

I think that whenever a connection is closed then I need to flush inputBuffer(index) for that index that has been closed...
I donot know what this command is doing

ReDim Preserve inputBuffer(Winsock1.UBound)

But lets say I have this situation

Index 1 --> Client #1
Index 2 --> Client #2
Index 3 --> Client #3

and then Client # 3 gets disconnected

and a new Client # 4 comes then the following will be the situation

Index 1 --> Client #1
Index 2 --> Client #2
Index 3 --> Client #4

and the inputBuffer(3) will contain the previous data as well as the newer data........Isn't it like this?

Also what will be the safest way to close the connection...... i.e. the client has received the file....Do I need to close the connection from the Client Side or the Server side ? and Is this line enough at the client side ?
WinsockClient.close

>> what will happen if both server and Client are connected but one of them gets disconnected from the internet while protocol \ command interchange is still in progress??
Will the ServerWinsock_Close( ) and ClientWinsock_Close( ) event be fired at both ends ?

I believe you will get an Error event from the winsock control notifying you, but I'm not actually sure as it is hard to create those conditions when both the server and client are being tested on the same machine. One thing you can do is always check the state of the connection before attempting to send anything:

If Winsock1(0).State = sckConnected Then
Winsock1(0).SendData "some data..."
End If

>> I need to flush inputBuffer(index) for that index that has been closed...

I am clearing the input buffer when the connection is accepted in ConnectionRequest():

If acceptIndex = -1 then we have to load up a new winsock control to handle the new connection. If this is the case then we also have to increase the size of the input buffer array to match the size of the winsock control array. This is what the

ReDim Preserve inputBuffer(acceptIndex)

line does. It makes the inputBuffer array the same size as the winsock control array. The Preserve word keeps the existing data in the array so it doesn't get lost.

>> Do I need to close the connection from the Client Side or the Server side ?

It doesn't matter but personally I would make the client side initiate the disconnect so that the close event will fire at the server side and make it clean up the winsock control array.

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 viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.