Jump to content

Zellpop

Members
  • Posts

    6
  • Joined

  • Last visited

Posts 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 smile.png 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 smile.png

     

    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

    • Upvote 1
  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 :blink:

    Hopefully is there enough information here to get brains go in to Hyper-mode

     

    Roy Vaulen

×
×
  • Create New...