Jump to content

Zellpop

Members
  • Posts

    6
  • Joined

  • Last visited

Everything posted by Zellpop

  1. I've searched the great Internet for a TCP server that handles multiple connections. And everyone uses a separate thread for each connection. After some trial and errors I think I've found a solution that uses two threads, where the second handles the communication. Some information before I start. Have been using VB.Net since its my «native» language For C# user it should be fairly easy to follow. When it comes to other languages I hope it will nudge you in the right direction. The .Net version is 4.5, but I think its more or less the same down to 2.0 Since VB.Net doesn't use a C language style/naming, I will try to translate some of the words to the C style syntax. Module = Static Class Sub = A routine/method that doesn't return a value Function = A routine/method that return a value Dim = A word used to declare a variable (Dim MyString as String) ReDim = resize an array New = The constructor key word (Dim MyCar as New Car) Dictionary(of Key, Value) = Strongly typed HashTable Queue(of Value) = Strongly typed Queue Imports = Using/Include... Namespace = I think that is the same all over the place CInt = Convert to Int32 CUInt = Convert to UInt32 Don't be alarmed about _Class naming. Its my way of naming Classes Here Is my code: First we make a class that holds all information about the connected user/client. Imports System.Net Imports System.Net.Sockets Namespace Network Public Class Client_Class Public MySocket As Socket Public SocketID As UInt32 End Class End Namespace MySocket holds all information about the connection, and SocketID is used by my/your code to find the «right» connection to send/receive bytes. The server need a way to store the incoming/outgoing bytes along with the ID of Sender/Receiver. So you'll need this message class Namespace Network Public Class Message_Class Private _ID As UInt32 Private _Message() As Byte Public Sub New(ID As UInt32, Message() As Byte) _ID = ID _Message = Message End Sub Public ReadOnly Property ID As UInt32 Get Return _ID End Get End Property Public ReadOnly Property Message As Byte() Get Return _Message End Get End Property End Class End Namespace As you can see the key word End is all over the place. It represent the end curly braces } This class has two fields, two properties and a constructor That was easy, now the hard part. Doing section by section I will try to explain what is going on. Imports System.Threading Imports System.Net Imports System.Net.Sockets Namespace Network Public Module ConnectionMGR Private _ConnectionMGRThread As New Thread(AddressOf ConnectionLoop) Private _ListOfConnections As New Dictionary(Of UInt32, Client_Class) Private _SendQueue As New Queue(Of Message_Class) Private _serverIP As IPAddress = IPAddress.Parse("127.0.0.1") Private _ServerPort As UInt16 = 5000 Private _ServerConnection As TcpListener Private _SocketID As UInt32 = 0 _ConnectionMGRThread is the thread that handles all the TCP communication, and starts in the Sub ConnectionLoop _ListOfConnections stores all connections as Key Value pair in a Dictionary (strongly typed Hastable) _SendQueue holds all messages that is going to be sent as Message_Class we made earlier. _ServerConnection is the mother of all the Sockets used. _SocketID is the unique value so we can find the correct client(will increase for each connection) Public Sub Start() _ConnectionMGRThread.Start() End Sub Public Sub Send(Message As Message_Class) _SendQueue.Enqueue(Message) End Sub Private Function NewSocketID() As UInt32 _SocketID += CUInt(1) Return _SocketID End Function Start starts the communication thread Send puts the message in the send queue. This should be thread safe since only one thread Peeks/Dequeues the queue NewSocketID returns +1 each time Private Sub NewConnections() Dim Client As New Client_Class Client.SocketID = NewSocketID() Client.MySocket = _ServerConnection.AcceptSocket _ListOfConnections.Add(Client.SocketID, Client) End Sub NewConnections is called every time a new connection is about to be established. Then we create a new Client instance of the Client_Class. Then we set the public fields .SocketID and .MySocket. Then we add it to _ListOfConnections Private Sub ConnectionLoop() Console.WriteLine("Communication Loop is listening") _ServerConnection = New TcpListener(_serverIP, _ServerPort) _ServerConnection.Start() Dim ReceiveBuffer() As Byte Dim ReceivedBytes As Integer Do While True If _ServerConnection.Pending() Then NewConnections() End If For Each Client As Client_Class In _ListOfConnections.Values If Client.MySocket.Available > 0 Then ReDim ReceiveBuffer(Client.MySocket.Available - 1) ReceivedBytes = Client.MySocket.Receive(ReceiveBuffer, ReceiveBuffer.Length, 0) Dim NewMessage As New Message_Class(Client.SocketID, ReceiveBuffer) Crypto.DeCryptMGR.DeCrypt(NewMessage) End If Next Do While _SendQueue.Count > 0 Dim SendClient As Client_Class Dim SendMessage As Message_Class SendMessage = _SendQueue.Dequeue() SendClient = _ListOfConnections.Item(SendMessage.ID) SendClient.MySocket.Send(SendMessage.Message, 0, SendMessage.Message.Length, SocketFlags.None) Loop Thread.Sleep(1) Loop End Sub End Module End Namespace When the thread is started, it begins in this Sub. All handling of any TCP/sockets is done by this thread. Hopefully it will keep it thread safe. ReciveBuffer is the array of bytes form incoming connections is stored. RecivedBytes is not in use here, but stores the amount of bytes recived. Now we enter the Loop that will never stop since True is always True. The first IF statement checks if someone is trying to connect For Each iterates through every client in the ListOfConnections to check if they have any incoming messages. If there is, resize the ReceiveBuffer to fit the new message. Create a new Message_Class and send it where you want. The code sends it to Crypto..... Do While checks if the _SendQueue contains any messages to send. If it does finds the correct Client and sends it of and does this until the _SendQueue.Count = 0. Then we Sleep for 1 millisecond and starts all over again. As you might have noticed, there are no error checking here. I was going for a minimalistic code example. But remember Murphy's law «everything that can go wrong will go wrong» This example doesn't take into account that connections might be slow/faulty/disconnected or otherwise broken. So to start everything up Module StartupSequence Sub Main() Network.ConnectionMGR.Start() Dim Message As Network.Message_Class Dim clientID As UInt32 Do While True clientID = CUInt(Console.ReadLine()) Message = New Network.Message_Class(clientID, {97, 95, 96, 93, 91, 100}) Network.ConnectionMGR.Send(Message) Loop End Sub End Module Sub Main() is where everything starts. The first client connected gets ID 1 next 2 and so on, in the console window you can write the ID you want to send to, and the client will receive the Array of Bytes {97, 95, 96, 93, 91, 100} Hope you will find it useful and create your own version in different languages. And share them with the non VB.Net users Theoretically this server could have 4.3 bill connections, but somehow I think its gonna meet the max long before that ( memory, network buffers, time for each iterations) Zellpop
  2. Thanks Cris and Flex. The technique I was thinking about, was to change a texture at runtime. And that it could be generated from any picture source into DDS and placed onto an entity (most likely a cube). I haven't been doing much with this buffer thingie, but I'll read me up on it. I'll Also look into Theora, although never used LUA The set color thing have most likely saved me allot of time Thanks for the response Zellpop
  3. I have a project going where I need to show dynamic content on the screen. At the startup of the program I don't know what I'll be showing, but I know I'll be getting information and pictures from Facebook and other sources. The content depends on voting and wishes form users Is there a good way to dynamically generate the DDS files so I can be showing content in a 3D space enviroment? Just using the "flat" DrawText is bit boring in this case Guess I can use a pack of 3D letters and animate them in LW. But still would like to import pictures on the fly Here is a link to show what I would like to do (doubt I'll be doing this much in LW any time soon in an easy way) http://www.outerspace-software.com/bixpack/pack.php?P=7 Zellpop
  4. Hi .net peoples of Leadwerks. I'm making a game (but who isn't) and have met some obstacles on the way, and are hoping that someone here can nudge me in the right direction. First som info about the game. Its a 3D platform game where you drive/roll/jump around the world using a Sphere or similar gadget/device. Controlling: W forward, S break, Space jump and right mouse button down for steering with the mouse left right. After reading the online documentation Im still a tad lost. The Local axis(sphere) ends up all over the place as a result of the rolling. So I found AddBodyTorque as a solution (witch hopefully gives me the possibility to use traction to surface at a later point), the ball is accelerating like I would expect. But making it turn becomes very hard (the torque axis will very easy "loose" direction) I see some solutions * Start knitting instead, and use my PC as a paper weight * Buy the game (if it exists) * Use move or similar command instead * Use a tyre/monobike contraption dymmy thingie thingie (so I can use torque) * See what Aggror have done in his C# Sphere Game (a fast glance I couldn't find Torque there) Im using LE.Net and VB.Net So if you have some ideas for me Im happy to read them Hopefully is there enough information here to get brains go in to Hyper-mode Roy Vaulen
×
×
  • Create New...