Ok Ladies gents, and frogs, i have edited the guide slightly and included the source code now, I hope people find this usefull :)
I have included it in the format of a word document with the source code all zipped up together,
PINO-
Printable View
Ok Ladies gents, and frogs, i have edited the guide slightly and included the source code now, I hope people find this usefull :)
I have included it in the format of a word document with the source code all zipped up together,
PINO-
Or you could post it in the CodeBank part of the forums..Quote:
Originally posted by Pino
Maybe a mod could make this a sticky ;)
Phreak
Bloody Ace, cheers mate that cleared up alot of my problems with winsock.
And made my latest project much easier to do :)
I'm so glad it helped :)Quote:
Originally Posted by thegreatone
Comments like that make me want to write more guides ;)
Thanks :)
one word, fanastic. ty for sharing this, I got a warm buzz when I compile it and tested it :) .
one question tho about the server, I was thinking bout similar where the server is actually on a website n friends connect to the server. An alternatively rather then someone having to have the server up n running where as it runs on a website's host. Possible features would include voice communicating etc basically a neat chat room similar to teamspeak if you have used it. Would this be hard?
Thanks for the comments, you cant host the server on a website, because they usually dont let you host .exe files and if they do its very expensive :(Quote:
Originally Posted by Shadows
Pino
ye I know, I was thinking about the server being programming in php or java and the client made in vb6. I'm still learning but from what I've heard, php has its own socket use for communicating with external programs or something on those lines. Basically winsock communicating with the alternative for php
Sorry Pino,
It just destroys one small point. Your's is just a Peer to Peer Chat application, Meaning: One Server for One Client. So you have a PeerServer which accepts connection for one client and a PeerClient which can connect only to one server. A Server, in complete, accepts more than one request from the client side.
To achieve this u need an Array of Winsock.
So, this code:
VB Code:
Private Sub Winsock_ConnectionRequest(ByVal requestID As Long) Winsock.Close 'this resets our socket ready to accept the incoming connection Winsock.Accept requestID 'accept the connection! End Sub
becomes
VB Code:
' Place a new Winsock array exclusively for Clients - wskClients(0) is the default Private Sub Winsock_ConnectionRequest(ByVal requestID As Long) newClient = wskClients.UBound + 1 Load wskClients(newClient) wskClients(newClient).Accept requestID 'accept the connection with our new Winsock ' So the Server continues to listen for more clients End Sub
Anyway, Very Good code for beginners.
Regards
HTH
Neo
Edit: Fixed vbcode tags - Hack
What i tend to find is hen learning to use winsock beginners find array very confusing and hence this aplication isnt Mulit-User chat but a very simple 2 person chat which demonstrates how to start a server connect and send data the fundementals of winsock, then if they wish to take it any further they can start to look at arrays but as I say this example is designed to be kept simple, i dont want to over complecate and confuse people :)
Anyhows i appriciate your comments and if you wish why not write up a guide demonstarating how to sue control arrays with winsock. I am in the middle of writing up the Network FAQ so if the guide is good I can link to it.
:)
Also just to pick up on the code you posted,
Faior enough but what happens if we have lots of clients connecting and then some leave?Over time you will have a large amount of un-used sockets which are just wasting server memory :( which isnt good if we are developing a serve rof some kind.Quote:
becomes
VB Code:
' Place a new Winsock array exclusively for Clients - wskClients(0) is the default Private Sub Winsock_ConnectionRequest(ByVal requestID As Long) newClient = wskClients.Count + 1 Load wskClients(newClient) wskClients(newClient).Accept requestID 'accept the connection with our new Winsock ' So the Server continues to listen for more clients End Sub
also this line
VB Code:
Private Sub Winsock_ConnectionRequest(ByVal requestID As Long)
if we are using an array should be....
VB Code:
Private Sub Winsock_ConnectionRequest([B]index as integer,[/B]ByVal requestID As Long)
:) Just to clear that up incase anyone takes anythign from this post.
Pino
Hey Pino,
Why dont you read my previous post properly! In a hurry i have forgot to close the [ vbcode ] properly. So, it ended up with a code line that made you not to notice the first line. I have specified you to create a new Winsock and name it as wskClients exclusively for Clients, and NOT to make the existing Winsock as an array. That way u need to change a lot of code, such as, to replace with Winsock(0) with Winsock everywhere.
So, y do you need this:
VB Code:
Private Sub Winsock_ConnectionRequest([color=red]Index As Integer,[/color] ByVal requestID As Long)
I closely look at codes before posting, So dont worry ;) . (Please look at my code carefully) My Code is correct:
VB Code:
Private Sub Winsock_ConnectionRequest(ByVal requestID As Long)
Because, it is only wskClients an Array and not the listening Winsock object.
Also, regarding the code:
I just gave a starting idea. If you want to continue, i will do it. It is obvious that u have to unload objects when they get closed, isnt it?
VB Code:
Private Sub wskClients_Error(Index As Integer, ByVal Number As Integer, _ Description As String, ByVal Scode As Long, ByVal Source As String, ByVal _ HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) Call wskClients_Close(Index) End Sub ' Clean up code Private Sub wskClients_Close(Index As Integer) wskClients(Index).Close Unload wskClients(Index) End Sub
But there is one small modification instead of using the .Count, its better to use the .UBound variable
So the Index variable keeps increasing. But the objects get unloaded. At point of time, when all clients quit all winsocks unload. I have a graph on Winsocks Clients Connection/DisConnection Time Line:
HTML Code:Slots Marked with x are loaded wskClients
No. Clients
1 2 3 4 5 6 7 8 9 10 .Count .UBound+1 <-- New Empty WinSock
_____________________________________________________
1 | x 1 2 New Client Connects
2 | x x 2 3 New Client Connects
3 | x x x 3 4 New Client Connects
4 | x x 2 4 Client 2 DisConnects
5 | x x x 3 5 New Client Connects
6 | x x x x 4 6 New Client Connects
7 | x x x 3 7 Client 4 Disconnects
8 | x x 2 4 Client 5 Disconnects
9 | x x x 3 5 New Client Connects
10 | x x 2 5 Client 3 Disconnects
11 | x x x 3 6 New Client Connects
12 | x x 2 6 Client 1 Disconnects
13 | x 1 6 Client 4 Disconnects
14 | 0 1 Client 5 Disconnects
15 | x 1 2 Cycles again in some combination
16 |___________________________________________
Hehe.. just a research i made.. to explain...
This means (.UBound + 1) always refers to a New Client
So the code becomes:
VB Code:
' Place a new Winsock array exclusively for Clients - wskClients(0) is the default Private Sub Winsock_ConnectionRequest(ByVal requestID As Long) newClient = wskClients.UBound + 1 ' instead of .Count + 1 Load wskClients(newClient) wskClients(newClient).Accept requestID 'accept the connection with our new Winsock ' So the Server continues to listen for more clients End Sub Private Sub wskClients_Error(Index As Integer, ByVal Number As Integer, _ Description As String, ByVal Scode As Long, ByVal Source As String, ByVal _ HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) Call wskClients_Close(Index) End Sub ' Clean up code Private Sub wskClients_Close(Index As Integer) wskClients(Index).Close Unload wskClients(Index) End Sub
Any Comments?
HTH
Neo
Yes please create a new thread if you wish to continue this one :) i'd prefer to keep this one simple as no to confuse the target programmer.
And if i read your code in-correctly i appoligise.
:)
hi..
i am stuck with the broadcast stuff...how???
this is my code here..--->
VB Code:
[COLOR=Green]Option Explicit Dim buffer() As Byte Dim lBytes As Long Dim temp As String Dim index As Long Private Sub cmdBrowse_Click() dlg.ShowOpen txtFile = dlg.FileName End Sub Private Sub cmdSend_Click() Dim index As Long cmdSend.Enabled = False lBytes = 0 ReDim buffer(FileLen(dlg.FileName) - 1) Open dlg.FileName For Binary As 1 Get #1, 1, buffer Close #1 Load wsTCP(1) wsTCP(1).RemoteHost = "255.255.255.255" wsTCP(1).RemotePort = 1111 wsTCP(1).Connect lblStatus = "Connecting..." End Sub Private Sub wsTCP_Close(index As Integer) lblStatus = "Connection closed" Unload wsTCP(1) End Sub Private Sub wsTCP_Connect(index As Integer) Dim i As Long ' Loop through the control array of clients and send the data on each one. For i = 1 To wsTCP.UBound wsTCP(index).SendData dlg.FileTitle & vbCrLf Next i End Sub Private Sub wsTCP_DataArrival(index As Integer, ByVal bytesTotal As Long) wsTCP(index).GetData temp If InStr(temp, vbCrLf) <> 0 Then temp = Left(temp, InStr(temp, vbCrLf) - 1) If temp = "OK" Then wsTCP(index).SendData buffer Else lblStatus = "Something wrong" Unload wsTCP(index) cmdSend.Enabled = True End If End Sub Private Sub wsTCP_SendComplete(index As Integer) If temp = "OK" Then lblStatus = "Send complete" temp = "" Unload wsTCP(1) cmdSend.Enabled = True End If End Sub Private Sub wsTCP_SendProgress(index As Integer, ByVal bytesSent As Long, ByVal bytesRemaining As Long) If temp = "OK" Then lBytes = lBytes + bytesSent lblStatus = lBytes & " out of " & UBound(buffer) & " bytes sent" End If End Sub[/COLOR]
need help urgently...
really appreciated a lot..
thanks..
ocw
Quote:
Originally Posted by CodeBlock
hi Hack,
i am doing problem this winsock. please enlighten me..
newClient = wskClients.UBound + 1
Load wskClients(newClient)
wskClients(newClient).Accept requestID 'accept the connection with our new Winsock
what is the "WskClient" doing in the prog?
???
ocw
WskClients is the name of the winsock control array,
Its just renamed from Winsock1.
The code above finds out which number is one above the UBound array and then creates a new socket on that number.
Is that what you mean?
Guys I must stress the main intention of this guide was to provide a simple beginning the winsock IE one client one server its going a bit beyond that now.
hi guys..
i have tried numerous times on this Winsock based on the guide lines and points mentioned in this forum. apart from so many connection_request methods discussed, i find it very interesting. HOwever, i have a question on how to send the data? if i have 10 listener waiting for my data, how can i broadcast to them? if i open two listener on different station within the network listening on the same port(port 1111), the error will pop out saying something like " adddress been used" and Control array element '2' doesn't exist. i really need yours guidances..
[vb code]
sending method
Private Sub cmdSend_Click()
Dim Index As Long
Dim i As Integer
cmdSend.Enabled = False
lBytes = 0
ReDim buffer(FileLen(dlg.FileName) - 1)
Open dlg.FileName For Binary As 1
Get #1, 1, buffer
Close #1
For i = 1 To wsClient.UBound + 1
Load wsClient(i) 'wsClient as my WinSock TCP protocol
wsClient(i).RemoteHost = "192.168.122.255" 'my broadcast address
wsClient(i).RemotePort = 1111
wsClient(i).Connect
lblStatus = "Connecting..."
Next i
[/vb code]
should i loop the wsClient like the way it had mentioned in this forum??? i have a similar connection_request methodas in the forum.
[vb code]
Private Sub wsClient_Connect(Index As Integer)
Dim i As Long
' Loop through the control array of clients and send the data on each one.
For i = 1 To wsClient.UBound + 1
wsClient(i).SendData dlg.FileTitle & vbCrLf
Next i
End Sub
[/vb code]
Greatly appreciated...
ocw
To send a message to all clients connected do this,
VB Code:
for i = 0 to winsock.ubound - 1 if winsock(i).state = sckconnected then wisnock(i).senddata "Data" end if doevents next i
thats all you need to do, no need to open up any more connectiosn etc.
this amkes no sence either...
VB Code:
For i = 1 To wsClient.UBound + 1 Load wsClient(i) 'wsClient as my WinSock TCP protocol wsClient(i).RemoteHost = "192.168.122.255" 'my broadcast address wsClient(i).RemotePort = 1111 wsClient(i).Connect lblStatus = "Connecting..." Next i
why are you looping to connect?
post me your client and sever applications.
pino
hihi..Quote:
Originally Posted by Pino
what about the code below?
[vb code]
Load wsClient(1)
wsClient(1).RemoteHost = "192.168.122.222" 'not a broadcast address (should i place a broadcast add to 192.168.122.255?)
wsClient(1).RemotePort = 1111
wsClient(1).Connect
lblStatus = "Connecting..."[/vb code]
should i made any changes to it?
real thanks..
??
ocw
What is that code supposed to do? Looks very strange.....
hihi..Quote:
Originally Posted by Pino
thanks Pino, this is my application. the objective of my application should be able to broadcast the all stations within the network.
real thanks..
??
ocw
sorry for the weird code given. i just want to try if i could send the data to all the stations within the network. i am not sure on winsock.Quote:
Originally Posted by Pino
sigh...
ocw
what does the app do? I can see deleting files, raises alarm bells....
Ok,
Wisnock(0) allwasy listens its the only one listening. from here it loads a new socket.
cahnge these parts,
VB Code:
Private Sub ws_sev_ConnectionRequest(index As Integer, ByVal requestID As Long) Dim i As Long i = wskClients.UBound + 1 Load ws_sev(newClient) ws_sev(newClient).Accept requestID End Sub
and change this also
VB Code:
Private Sub cmdRun_Click() If cmdRun.Caption = "Run" Then cmdRun.Caption = "Stop" ws_sev(0).LocalPort = 1111 ws_sev(0).Listen Else ws_sev(0).Close cmdRun.Caption = "Run" End If End Sub
hihi..Quote:
Originally Posted by Pino
i have change the code. now the error throws "connection close" at the statue label.
ocw
i didnt look through the rest of the code, i havent had chance, and i'm not runnign the program, until you tell me what it does, I cant help you any further :(
Pino
hihi..Quote:
Originally Posted by Pino
the application will override the file if there are duplicate file name. the main objective to this applicaition is to send the file to all stations within the network (broadcasting)...
now, the application only able to send to the one port or one station.
thanks Pino.
Best regards
ocw
I cant make head nor tail of the code, the server is supposed to send the file out right?
I think you best go back to basics, cut all the disabling commands etc, and just stay winsock, then really focus on what is supposed to go on.
Pino
sorry fro the messy codes, the server is suppose to listen for the data, while the client is suppose to send the data. by using the localhost ip, i am able to send to my station destop. but when i change the RemoteIP to the "192.168.122.255" the broadcast add, it fails to broadcast the data, even to my station.Quote:
Originally Posted by Pino
thus, i have wondering is my connection_request and the sending of data is correct.
thanks pal
ocw
First of all, you can't broadcast with TCP only UDP.
And with UDP, the broadcast IP is 255.255.255.255 (and it works only for local network)
The example Pino gave to broadcast, does not really broadcast, it's simply sending a message to everyone who is connected.
For example if you have 10 connections, and you want to send the same message to all 10, then you send to the first one, then the second, and so on.
That means that if you have a message that is 100 bytes (lets say), you will end up sending 100 * 10 = 1000 bytes. Wich is NOT broadcast.
Broadcast means you send 10 bytes ONCE and everyone gets the message.
Also, what you want is multicast, not broadcast, you want a select # of people to get the message, not EVERYONE ?
So, if you REALLY want to broadcast you have to switch to UDP protocol. Also don't forget that even that, works only for local network.
im having some big problms with my code can someone tell me why when the client sends something it doesnt appear in the server screen and am i doing the multiple connections thing right?
Server
VB Code:
Dim msgarrived As String Dim i As Integer Private Sub cmdsend_Click() For i = 0 To server.ubound - 1 If server(i).State = sckConnected Then server(i).SendData txtnickname.Text & ": " & txtmsg.Text txtchat.Text = txtnickname.Text & ": " & txtmsg.Text & vbNewLine txtmsg.Text = "" End If DoEvents Next i End Sub Private Sub Winsock_ConnectionRequest(ByVal requestID As Long) newClient = server.ubound + 1 Load server(newClient) server(newClient).Accept requestID End Sub Private Sub server_DataArrival(Index As Integer, ByVal bytesTotal As Long) server(i).GetData msgarrived txtchat.Text = msgarrived & vbNewLine End Sub Private Sub server_Error(Index As Integer, ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) Call server_Close(Index) End Sub Private Sub server_Close(Index As Integer) server(Index).Close Unload server(Index) End Sub
Client
VB Code:
Option Explicit Dim msgarrived As String Dim i As Integer Private Sub cmdconnect_Click() client(i).Connect txtip.Text, txtportnum.Text MsgBox "Connected To " & txtip.Text End Sub Private Sub cmdsend_Click() For i = 0 To client.ubound - 1 If client(i).State = sckConnected Then client(i).SendData txtnickname.Text & ": " & txtmsg.Text txtchat.Text = txtnickname.Text & ": " & txtmsg.Text & vbNewLine txtmsg.Text = "" End If DoEvents Next i End Sub Private Sub Winsock_ConnectionRequest(ByVal requestID As Long) newClient = server.ubound + 1 Load client(newClient) client(newClient).Accept requestID End Sub Private Sub client_Error(Index As Integer, ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) Call client_Close(Index) End Sub Private Sub client_Close(Index As Integer) client(Index).Close End Sub
change,
VB Code:
Private Sub server_DataArrival(Index As Integer, ByVal bytesTotal As Long) server(i).GetData msgarrived txtchat.Text = msgarrived & vbNewLine End Sub
on the server to say
VB Code:
Private Sub server_DataArrival(Index As Integer, ByVal bytesTotal As Long) server(index).GetData msgarrived txtchat.Text = msgarrived & vbNewLine End Sub
that will work!
A Good Muliti Connection Chat App should have some strict rules:
Server Rules:
1. Must Run only *ONCE* and listen at a specific port
2. Must Accept connections from clients by transfering the incoming connection to a new Socket, thus keeping the Listening socket available for more clients to connect.
3. Cannot have a User-Interface (its not a Client, please remember) to interact with a User (Except for Admin Messages and advanced stuff)
4. may try to redirect most messages for simplicity
5. Should follow a Protocol common to both the client and the server. Protocol may be simple from user-defined to complex such as IRC, IRCX ... etc
Client Rules:
1. Should Connect to a Server using just one Winsock - NO ARRAYS
2. Any new client starting, should start on its own new Application (new process)
4. Can have User Interface for Client Interaction
3. Follow the same protocol as supported by the Server
See whether u follow the above rules
For a person to chat with another person, 3 apps will run at the least.
One will be the server and the other two will be the two person's client app.
So if Person 1 wants to send message to Person 2, the client1 first contacts the server the server then send the message to client 2.
Thus, the server is like a mediator.
Due to these reasons, u have to first remove text boxes from ur server app. The Server app cannot act like a client, hehe, Can it? :sick: :)
And Regarding Protocols, its better to send your messages with some extra commands along with ur message. And dont forget to seperate your message with a delimiter. 99% of Chat Clients use vbCrLf as the message seperator.
So your code can look like this after some modifications:
Server:
VB Code:
Dim msgarrived As String Dim i As Integer 'Private Sub cmdsend_Click() 'For i = 0 To server.ubound - 1 ' If server(i).State = sckConnected Then ' server(i).SendData txtnickname.Text & ": " & txtmsg.Text ' txtchat.Text = txtnickname.Text & ": " & txtmsg.Text & vbNewLine ' txtmsg.Text = "" ' End If ' DoEvents 'Next i 'End Sub Private Sub Winsock_ConnectionRequest(ByVal requestID As Long) newClient = server.ubound + 1 Load server(newClient) server(newClient).Accept requestID End Sub Private Sub server_DataArrival(Index As Integer, ByVal bytesTotal As Long) Dim Data As String server(Index).GetData Data, vbString ' If we have any data remaining from the previous DataArrival Call Data = Messages(Index) & Data Dim Messages() As String Messages = Split(Data, vbCrLf) For i = LBound(Messages) To UBound(Messages) - 1 ParseMessage Messages(i) Next i ' We are adding the last message as buffer to prevent data loss server(Index).Tag = Messages(i) End Sub Private Sub server_Error(Index As Integer, ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) Call server_Close(Index) End Sub Private Sub server_Close(Index As Integer) server(Index).Close Unload server(Index) End Sub Sub ParseMessage(Message As String) Dim CMDs() As String Dim RealMessage As String Dim i As Long ' Message can be like ' MSG MyNickName :hi all ' PM MyNickName CodeBlock :hi mate ;) ' Seperate Commands from Real Message, Colon ":" is our seperator i = InStr(1, Message, ":") RealMessage = Mid$(Message, i + 1) ' get the commands such as MSG or PM CodeBlock ... etc Message = Left$(Message, i - 1) CMDs = Split(Message, " ") Select Case CMDs(0) Case "MSG": ' Cmds(1) has the nickname of the sender ' This command means message to all For i = 0 To UBound(server) ' MSG SenderNick:Real Message server(i).SendData "MSG " & CMDs(1) & ":" & RealMessage Next i Case "PM": ' Cmds(1) has the nickname of the receiver '... End Select End Sub
Please, you have to look at a users ability and where they are in, learning or expert. he/She is clearly learning so this stuff is not nessercery. And a server can have an interface/control pannel.
As i have mentioned before please create anew thread if you wish to make an advanced guide. Again I will quote myself. Before i have to have this thread split.
Quote:
Guys I must stress the main intention of this guide was to provide a simple beginning the winsock IE one client one server its going a bit beyond that now.
I never liked leaving holes in my array of servers so I use this simple function to load the next server.
VB Code:
Function LoadNextServer(wsServer) As Long Dim wsck Dim i As Long i = 0 For Each wsck In wsServer If wsck.Index > i Then LoadNextServer = i Load wsServer(i) Exit Function Else i = i + 1 End If Next LoadNextServer = i Load wsServer(i) End Function
Then you would call it like thisVB Code:
Private Sub Server_ConnectionRequest(Index As Integer, ByVal requestID As Long) Dim newClient As Long If Index = 0 Then 'this is the listening server 'load a new control to talk to this client newClient = LoadNextServer(Server) Server(newClient).Accept requestID Server(newClient).SendData "Hello: you are connected" End If End Sub
Pino, sorry if you think this is too advanced, but I think it is basic.
i need clarification on this one. in the winsock array, say for example i loaded 5 winsocks because there are 5 clients that connected, if the starting index for my winsock array is 0, then winsock.ubound would be 4,right? and when another client would connect, i would load winsock(5) to accept that connection, and calling winsock.ubound would give me 5, is this right?
and then for example winsock(1) is closed and unloaded, only 5 winsocks would be left because winsock(1) is removed but winsock.ubound would still be 5, right? because the array index would not rollback even if you unload an item that is part of the array.
so i guess in a multi client-server application, it is not safe to iterate thru all clients using something like:
VB Code:
for i=0 to ubound(sckClients) sckClients(i).senddata "blah...blah...." next i
it is better i think to use a for each loop.
Ok, here is how it works
Winsock(0) allways listens, when it gets a connection request it passes it on to the next avalible winsock,
Winsock(1), Winsock (2) etc
as for the loop here is how to senddata to all connected clients,
VB Code:
For i = winsock.ubound - 1 if winsock(i).state = sckconnected then winsock(i).senddata "hello" end if doevents next i
Hope that helps, if you have any furthur questions could you make a new post in the network section?
Thanks
Pino
I think Pino was half asleep when he wrote this. For one thing it won't work if a control has been unloaded.Quote:
VB Code:
For i = winsock.ubound - 1 if winsock(i).state = sckconnected then winsock(i).senddata "hello" end if doevents next i
Instead I would do thisVB Code:
Dim wsk As Winsock For Each wsk In Winsock If wsk.State = sckConnected Then _ wsk.SendData "Hello" Next
Nice polite person you are :rolleyes:
Can I ask how a sockect would be unloaded? seriosuly, I have never had a problem.