| Mirage Source http://web.miragesource.net/forums/ |
|
| Alternative IOCP Tutorial http://web.miragesource.net/forums/viewtopic.php?f=210&t=1468 |
Page 1 of 2 |
| Author: | Xlithan [ Thu Mar 08, 2007 5:48 pm ] |
| Post subject: | Alternative IOCP Tutorial |
This version of the tutorial was released on the ED forums, but this is the one I used to add to Mirage Source which seemed to work first time. Again, credit goes to Verrigan for this, and Aranshada for writing the tutorial. This tutorial will NOT work with Windows 95/98/ME Servers In order to do this tut, you will need to download this .dll file and register it. THIS IS A NECESSITY FOR THIS TUTORIAL!!! http://aranshada.hopto.org/Elysium/Downloads/COMSocketServer.dll -=: Server-Side :=- First thing's first, go to Project > References... and scroll down until you find JetByte Socket Server 1.0 Type Library. Check the box beside it and click OK. Download Sonires classes, these are guaranteed to work in MSE (Tested myself). http://www.freewebs.com/msebuild1/classes.rar To add these to your server project after downloading them, go to Project > Add Class Module, and click the Existing tab, and select the a module that you downloaded. Repeat this until you have all three class modules added to your project. Now that we have the class modules out of the way, we have to go through the rest of the server and change some stuff. So, what do you think we'll need to change first? We'll need to change the methods for creating the sockets, destroying the sockets, and anything that checks a socket for a connection. In modServerTCP, add these declarations at the top. Code: ' Our GameServer and Sockets objects for the TCP interaction Public GameServer As clsServer Public Sockets As colSockets Those will serve to be our objects that we will control all TCP interaction from. In modGeneral, find Sub InitServer. Find: Code: ' Get the listening socket ready to go frmServer.Socket(0).RemoteHost = frmServer.Socket(0).LocalIP frmServer.Socket(0).LocalPort = GAME_PORT Comment all of it out or just delete it if you'd like. Either way, add this below it: Code: Set GameServer = New clsServer That will set our GameServer object as a new clsServer class. Just below that you'll see this: Code: ' Init all the player sockets Call SetStatus("Initializing player array...") For i = 1 To MAX_PLAYERS Call ClearPlayer(i) Load frmServer.Socket(i) Next i Comment out Load frmServer.Socket(i) and add this below it: Code: Call GameServer.Sockets.Add(CStr(i)) So the entire thing should look like this: Code: ' Init all the player sockets Call SetStatus("Initializing player array...") For i = 1 To MAX_PLAYERS Call ClearPlayer(i) 'Load frmServer.Socket(i) Call GameServer.Sockets.Add(CStr(i)) Next i Keep looking in that same sub until you find this: Code: ' Start listening frmServer.Socket(0).Listen Comment out frmServer.Socket(0).Listen and add this below it: Code: GameServer.StartListening Now, still in modGeneral, find Sub DestroyServer. Inside of Sub DestroyServer, find this: Code: For i = 1 To MAX_PLAYERS Call SetStatus("Unloading sockets and timers... " & i & "/" & MAX_PLAYERS) DoEvents Unload frmServer.Socket(i) Next Change all of that to this: Code: For i = 1 To MAX_PLAYERS Call SetStatus("Unloading sockets and timers... " & i & "/" & MAX_PLAYERS) DoEvents 'Unload frmServer.Socket(i) Call GameServer.Sockets.Remove(CStr(i)) Next Set GameServer = Nothing Now go to Sub UpdateCaption in modServerTCP. Change the whole sub to this: Code: Sub UpdateCaption() frmServer.Caption = GAME_NAME & " - Server - Powered By Elysium Source" frmServer.lblIP.Caption = "IP Address: " & frmServer.Socket(0).LocalIP frmServer.lblPort.Caption = "Port: " & STR(GameServer.LocalPort) frmServer.TPO.Caption = "Total Players Online: " & TotalOnlinePlayers Exit Sub End Sub If you'll notice, the only thing changed is that we use GameServer.LocalPort to show what the port is. I left the frmServer.Socket(0).LocalIP in there so it'd be easier to find out what my computer's private IP is. What's our next target? Sub SendDataTo. It is also located in modServerTCP. Change the entire thing to this: Code: Sub SendDataTo(ByVal index As Long, ByVal Data As String) Dim dbytes() As Byte dbytes = StrConv(Data, vbFromUnicode) If IsConnected(index) Then GameServer.Sockets.Item(index).WriteBytes dbytes DoEvents End If 'If IsConnected(index) Then ' frmServer.Socket(index).SendData Data ' DoEvents 'End If End Sub There is also another one in clsCommands. Be sure you change that one too if you intend on sending packets from the Main.txt. You can see where I simply commented out the old code and added the new above it. This also shows you the method used for sending a packet. So... we've changed how it loads the object, destroys it, and how it sends data. What's next? Find Function IsConnected in modServerTCP. Change the whole function to this: Code: Function IsConnected(ByVal index As Long) As Boolean If GameServer.Sockets.Item(index).Socket Is Nothing Then IsConnected = False Else IsConnected = True End If 'If frmServer.Socket(index).State = sckConnected Then ' IsConnected = True 'Else ' IsConnected = False 'End If End Function There is also another one in clsCommands. Be sure you change that one, too. Now that we can't exactly check the socket's state against VB's Winsock Constants, we can simply check to see if a certain socket Is Nothing. If it Is Nothing, then it hasn't been initialized, meaning that there isn't a live connection, so we return false. Otherwise, it's true. Now we'll tackle all of the subs that are fired when a connection is received or closed. In modServerTCP, find Sub AcceptConnection. Change the whole thing to this: Code: Sub AcceptConnection(Socket As JBSOCKETSERVERLib.ISocket) Dim i As Long i = FindOpenPlayerSlot If i <> 0 Then ' Whoho, we can connect them 'frmServer.Socket(i).Close 'frmServer.Socket(i).Accept SocketId Socket.UserData = i Set GameServer.Sockets.Item(CStr(i)).Socket = Socket Call SocketConnected(i) Socket.RequestRead Else Socket.Close End If End Sub Find Sub CloseSocket in the same module. Change the whole sub to this: Code: Sub CloseSocket(ByVal index As Long) ' Make sure player was/is playing the game, and if so, save'm. If index > 0 Then Call LeftGame(index) Call TextAdd(frmServer.txtText(0), "Connection from " & GetPlayerIP(index) & " has been terminated.", True) 'frmServer.Socket(index).Close Call GameServer.Sockets.Item(index).ShutDown(ShutdownBoth) Set GameServer.Sockets.Item(index).Socket = Nothing Call UpdateCaption Call ClearPlayer(index) End If End Sub Now to deal with IncomingData. Also in modServerTCP, find Sub IncomingData. Change the whole sub to this: Code: Sub IncomingData(Socket As JBSOCKETSERVERLib.ISocket, Data As JBSOCKETSERVERLib.IData) 'On Error Resume Next Dim Buffer As String Dim dbytes() As Byte Dim Packet As String Dim top As String * 3 Dim Start As Integer Dim index As Long Dim DataLength As Long dbytes = Data.Read Socket.RequestRead Buffer = StrConv(dbytes(), vbUnicode) DataLength = Len(Buffer) index = CLng(Socket.UserData) If Buffer = "top" Then top = STR(TotalOnlinePlayers) Call SendDataTo(index, top) Call CloseSocket(index) End If Player(index).Buffer = Player(index).Buffer & Buffer Start = InStr(Player(index).Buffer, END_CHAR) Do While Start > 0 Packet = Mid(Player(index).Buffer, 1, Start - 1) Player(index).Buffer = Mid(Player(index).Buffer, Start + 1, Len(Player(index).Buffer)) Player(index).DataPackets = Player(index).DataPackets + 1 Start = InStr(Player(index).Buffer, END_CHAR) If Len(Packet) > 0 Then Call HandleData(index, Packet) End If Loop ' Check if elapsed time has passed Player(index).DataBytes = Player(index).DataBytes + DataLength If GetTickCount >= Player(index).DataTimer + 1000 Then Player(index).DataTimer = GetTickCount Player(index).DataBytes = 0 Player(index).DataPackets = 0 Exit Sub End If ' Check for data flooding If Player(index).DataBytes > 1000 And GetPlayerAccess(index) <= 0 Then Call HackingAttempt(index, "Data Flooding") Exit Sub End If ' Check for packet flooding If Player(index).DataPackets > 25 And GetPlayerAccess(index) <= 0 Then Call HackingAttempt(index, "Packet Flooding") Exit Sub End If End Sub What else is there? What else deals directly with the connection? GetPlayerIP. There are two instances of GetPlayerIP. One is in modTypes, and the other is in clsCommands. Change both of them to this: Code: Function GetPlayerIP(ByVal index As Long) As String 'GetPlayerIP = frmServer.Socket(index).RemoteHostIP GetPlayerIP = GameServer.Sockets.Item(index).RemoteAddress End Function Also, in modGeneral, find Sub ServerLogic. Change the whole thing to this: Code: Sub ServerLogic() 'Dim i As Long ' Check for disconnections 'For i = 1 To MAX_PLAYERS ' If frmServer.Socket(i).State > 7 Then ' Call CloseSocket(i) ' End If 'Next Call CheckGiveHP Call GameAI End Sub (Good catch, Pingu.) There's not really any need to check for this anymore since I don't think the socket state COULD be like that with COMSocketServer. Now, go to frmServer. Find these subs: Code: Private Sub Socket_Close(index As Integer) Call CloseSocket(index) End Sub Private Sub Socket_ConnectionRequest(index As Integer, _ ByVal requestID As Long) Call AcceptConnection(index, requestID) End Sub Private Sub Socket_DataArrival(index As Integer, _ ByVal bytesTotal As Long) If IsConnected(index) Then Call IncomingData(index, bytesTotal) End If End Sub DELETE ALL OF THEM. They will only cause errors now. I believe that's all there is for the Server-Side of things. On to the client! -=: Client-Side :=- Don't worry, we won't be here long. In the client, go to modClientTCP and find Sub SendData. Change the whole thing to this: Code: Sub SendData(ByVal data As String)
Dim dbytes() As Byte dbytes = StrConv(data, vbFromUnicode) If IsConnected Then 'If InGame Then 'frmMirage.Socket.SendData Encrypt(data, EncryptPassword) 'Else 'frmMirage.Socket.SendData Encrypt(data, defaultEncryptPassword) 'End If frmMirage.Socket.SendData dbytes DoEvents End If End Sub Done with the Client-Side stuff! Now, isn't the client much easier than the server? Optionally, you might also want to set the MAX_PLAYERS in your Data.ini to something much higher. It's less stress on the server now since it doesn't have to load up a new Winsock object for every connection. Now it just adds a new object to a collection. I've seen some servers with IOCP that had MAX_PLAYERS set at 500. I've seen another one with it set at 1000. That's really just personal preference, though. Now, I'm pretty sure I didn't miss anything. If anyone gets any errors after trying this tut, copy/paste the section of code that is highlighted as well as the surrounding code, and I'll see if there's something that I forgot to put in the tut. Credit for the code in this tutorial goes to Dave's Valkorian Engine source because I looked at all of the code in there to find out how to do this. Some credit also goes to Pingu for requesting this tutorial in the first place. |
|
| Author: | Joost [ Thu Mar 08, 2007 5:54 pm ] |
| Post subject: | |
Due to people trying to 'fake' Elysium, you can't repost tutorials from ES. We should have a thread about that somewhere. Anyway, since this is MS, I don't really care, I'll check with Aran if it's okay with him too, and if not, I'll update this post. |
|
| Author: | Xlithan [ Thu Mar 08, 2007 5:59 pm ] |
| Post subject: | |
Oh ok. I didn't know. My view on open source programming and code sharing is slightly different than others then. |
|
| Author: | Godlord [ Thu Mar 08, 2007 6:04 pm ] |
| Post subject: | |
And there are also some Run-time errors on this so far as I know. RTE: 91 and another one which I don't remember. |
|
| Author: | William [ Thu Mar 08, 2007 6:07 pm ] |
| Post subject: | |
Quote: Due to people trying to 'fake' Elysium, you can't repost tutorials from ES
The tutorial was originaly posted on MS forum, no more than right to share a modified here. |
|
| Author: | Joost [ Thu Mar 08, 2007 6:10 pm ] |
| Post subject: | |
GameBoy wrote: Oh ok. I didn't know. My view on open source programming and code sharing is slightly different than others then.
I agree mostly. The problem was, at one point there even was an 'Elysium Underground' stealing all our tutorials and, basicly, everything. That kinda shit pisses me off. I have totally no problems with it being at MS though. |
|
| Author: | Verrigan [ Thu Mar 08, 2007 6:33 pm ] |
| Post subject: | |
Some tutorials are buggy... Some people who try to follow tutorials are buggy... Aranshada created the Elysium tutorial on his (her?) own, based off of information that he received from Dave's engine, and did not know my original tutorial existed here. Either way, both tutorials accomplish the same thing.. You cannot do these tutorials if you don't understand how to properly fix bugs that come up while trying to do them. Also, I believe the RTE 91 is Object or With Block Variable not set? If so, you need to make sure the comsocketserver.dll file is registered.. If you don't know how to register an activex component, then you probably shouldn't be writing programs that use 3rd party (non-Micro$oft) activex components. |
|
| Author: | Godlord [ Thu Mar 08, 2007 6:48 pm ] |
| Post subject: | . |
Verrigan it was tried with the .DLL registered. It is an error in the tutorial I don't know why it shows up but the tutorial can give some problems. |
|
| Author: | Xlithan [ Thu Mar 08, 2007 6:55 pm ] |
| Post subject: | |
Paste the code to me. I know I had to modify something myself, but it wasn't major. Did you add the DLL to the references? |
|
| Author: | Verrigan [ Thu Mar 08, 2007 6:59 pm ] |
| Post subject: | |
Ahh... There are some places where it checks a socket, and that socket doesn't exist... Either because it hasn't been created yet, or it has been deleted... (set socket = nothing) In either case, if you perform a 'If Socket Is Nothing Then Exit <Sub/Property/Function>' you will avoid this error in such cases. [Edited because I forgot the 'Then'... Bolded it for ya. |
|
| Author: | Sephiroth187 [ Tue Mar 13, 2007 12:35 pm ] |
| Post subject: | |
just make sure you make a proper installation for clients to use this. Perhaps in the initialization stage of the program; If a error comes up-; Code: Sub Main()
On local error goto exts: exit sub exts: if err.number = 91 then If Len(Dir(App.Path & "\COMSocketServer.dll")) > 0 Then If MsgBox("Do you give permission to copy COMSocketServer.dll(Run time file) into Windows\system32\ folder?", vbQuestion + vbYesNo) = vbNo Then End Call FileCopy(App.Path & "\COMSocketServer.dll", "\Windows\System32\COMSocketServer.dll") kill app.path & "\COMSocketServer.dll" Shell "regsvr32 \Windows\System32\COMSocketServer.dll /s" MsgBox "Please restart this program, if problems persist contact administrator", vbInformation End End If end sub It should hopefully work. This is also assuming the user is "innocent" with expected computer settings. |
|
| Author: | Coke [ Tue Mar 13, 2007 1:03 pm ] |
| Post subject: | |
What pisses me off is elysium was made from konfuze, which wouldnt of existed without this community; so if people want to share tutorials i think they bloody well can =P |
|
| Author: | Joost [ Tue Mar 13, 2007 2:41 pm ] |
| Post subject: | |
Fox wrote: What pisses me off is elysium was made from konfuze, which wouldnt of existed without this community; so if people want to share tutorials i think they bloody well can =P
What pisses me off is that MS was made in Visual Basic, so Microsoft should have all rights to MS. Your logic is almost as good as a drunk man's logics. Almost. |
|
| Author: | Coke [ Tue Mar 13, 2007 2:43 pm ] |
| Post subject: | |
William wrote: Quote: Due to people trying to 'fake' Elysium, you can't repost tutorials from ES The tutorial was originaly posted on MS forum, no more than right to share a modified here. |
|
| Author: | Xlithan [ Tue Mar 13, 2007 2:48 pm ] |
| Post subject: | |
No Joost it doesn't work like that. That's like saying my music that I created belongs to Steinberg because I recorded it with their software. There are parts of Elysium which are still original parts of Mirage Source. |
|
| Author: | Joost [ Tue Mar 13, 2007 3:03 pm ] |
| Post subject: | |
Fox wrote: William wrote: Quote: Due to people trying to 'fake' Elysium, you can't repost tutorials from ES The tutorial was originaly posted on MS forum, no more than right to share a modified here. And William is wrong. Aran ripped this tutorial from one of Verrigan's sources. So you can go around quoting people, but generally speaking, I'm correct more often than the average person. @GameBoy, even if some parts are the same, MS has no license, so Fox can't go around telling me I have to do things because it was made from Mirage or konfuze, or whatever. |
|
| Author: | Coke [ Tue Mar 13, 2007 3:08 pm ] |
| Post subject: | |
Verrigan is considered a very valued part of the community, i am sure he would want adaptations on his work shared. |
|
| Author: | Joost [ Tue Mar 13, 2007 3:23 pm ] |
| Post subject: | |
Yes, and you don't see me complaining, do you? I just stated that normally, normally people can't repost tuts from ES. |
|
| Author: | Verrigan [ Tue Mar 13, 2007 4:15 pm ] |
| Post subject: | |
Sephiroth187 wrote: just make sure you make a proper installation for clients to use this. Perhaps in the initialization stage of the program; If a error comes up-;
Code: Sub Main() On local error goto exts: exit sub exts: if err.number = 91 then If Len(Dir(App.Path & "\COMSocketServer.dll")) > 0 Then If MsgBox("Do you give permission to copy COMSocketServer.dll(Run time file) into Windows\system32\ folder?", vbQuestion + vbYesNo) = vbNo Then End Call FileCopy(App.Path & "\COMSocketServer.dll", "\Windows\System32\COMSocketServer.dll") kill app.path & "\COMSocketServer.dll" Shell "regsvr32 \Windows\System32\COMSocketServer.dll /s" MsgBox "Please restart this program, if problems persist contact administrator", vbInformation End End If end sub It should hopefully work. This is also assuming the user is "innocent" with expected computer settings. You should always ensure that libraries are registered at installation time. Other things to consider are: 1) You should make sure the users who will be installing your application know you will be registering libraries.. 2) Learn to nest your code. I wrote a very simple tutorial on this concept once, which I have copied back over to these forums. Find it here. Just a little constructive criticism.. Don't be offended by my opinions. |
|
| Author: | Xlithan [ Tue Mar 13, 2007 6:34 pm ] |
| Post subject: | |
CodeFixer for the win |
|
| Author: | Sephiroth187 [ Wed Mar 14, 2007 12:16 am ] |
| Post subject: | |
Verrigan wrote: You should always ensure that libraries are registered at installation time. Other things to consider are:
1) You should make sure the users who will be installing your application know you will be registering libraries.. 2) Learn to nest your code. I wrote a very simple tutorial on this concept once, which I have copied back over to these forums. Find it here. Just a little constructive criticism.. Don't be offended by my opinions. Ah dude I crave criticism, I get disappointed if no one criticises, thanks for it. Dont worry if I get offended, I will only get offended if I generally think its an unjust comment, which yours was definantly not - even if I do get offended I dont flame, its never my nature. I will tell you what I thought of the comment but thats about it. Yes, I did realise I should of made the user aware that I will also be registering, but I was assuming that if the file was being copied into a folder labeled such as "system32" the user would generally think that it is important. But this is easily changed :p Ah I do nesting generally all the time. This was a quick example. But I will consider it for writing other examples, kinda my first time sharing knowledge |
|
| Author: | Verrigan [ Wed Mar 14, 2007 3:28 am ] |
| Post subject: | |
Thanks, Sephiroth. I'm glad you were not offended. |
|
| Author: | Sephiroth187 [ Thu Mar 15, 2007 8:25 am ] |
| Post subject: | |
question : This IOCP thing. Does it require Winsock to work. I've been trying to mess around with it, I'm confused how to get it to connect. Anyone have any good tutorial references? I will continue to mess about with it regardless... It seems interesting. *edit* Ah I managed to get it working dont worry |
|
| Page 1 of 2 | All times are UTC |
| Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |
|