Sockets bother me

05/17/2017 16:27 iBotx#1
Hello,

I have came into a problem with my source, i'm using async sockets and after a while their memory usage increases rapidly, i think it's something related to something called "overlapping", i've tried googling it but couldn't find a solution. Any ideas? or tutorials how to write effecient sockets.
05/17/2017 18:16 Spirited#2
Post the socket system here, and maybe we can take a look at it.
05/17/2017 19:40 iBotx#3
The socket system is inspired by Redux and Phoenix. I've been using this for a while and i think the problem comes from here.

PHP Code:
using System;
using System.Net;
using System.Text;
using System.Linq;
using System.Net.Sockets;

namespace 
PureConquer.Network.ServerSocket
{
    public 
delegate void NetworkClientConnection(Wrapper client);
    public 
delegate void NetworkClientReceive(byte[] bufferint lengthWrapper client);
    public class 
SocketServer
    
{
        public 
Socket Socket get; private set; }
        public 
IPEndPoint LocalEndPoint get; private set; }
        public 
NetworkClientConnection OnConnect;
        public 
NetworkClientReceive OnReceive;
        public 
NetworkClientConnection OnDisconnect;
        public 
BruteForceAttackProtection AttackProtector;

        public 
int ClientBufferSize;
        public 
SocketServer(uint maximum 50uint banTime 60)
        {
            
AttackProtector = new BruteForceAttackProtection(maximumbanTime);
        }

        public 
void Prepare(int portint backlogIPProtectionLevel protectionLevel)
        {
            
LocalEndPoint = new IPEndPoint(IPAddress.Anyport);
            
Socket = new Socket(AddressFamily.InterNetworkSocketType.StreamProtocolType.Tcp);
            
Socket.Bind(LocalEndPoint);
            
Socket.SetIPProtectionLevel(protectionLevel);
            
Socket.NoDelay true;
            
Socket.Listen(backlog);
        }

        public 
void BeginAccept()
        {
            
Socket.SetSocketOption(SocketOptionLevel.SocketSocketOptionName.KeepAlivefalse);
            
Socket.SetSocketOption(SocketOptionLevel.SocketSocketOptionName.DontLingertrue);
            
Socket.BeginAccept(Acceptnull);
        }

        private 
void Accept(IAsyncResult result)
        {
            
Socket clientSocket;
            try
            {
                
clientSocket Socket.EndAccept(result);
            }
            catch (
SocketException)
            {
                
BeginAccept();
                return;
            }
            if (
AttackProtector.Authenticate(clientSocket))
            {
                
clientSocket.ReceiveBufferSize ClientBufferSize;
                var 
client = new Wrapper(thisclientSocketClientBufferSize);
                
InvokeOnConnect(client);
                
client.BeginReceive();
            }
            else
                
clientSocket.Disconnect(false);
            
BeginAccept();
        }

        public 
void InvokeOnConnect(Wrapper client)
        {
            if (
OnConnect != null)
                
OnConnect(client);
        }

        public 
void InvokeOnReceive(byte[] bufferint lengthWrapper client)
        {
            if (
OnReceive != null)
                
OnReceive(bufferlengthclient);
        }

        public 
void InvokeOnDisconnect(Wrapper client)
        {
            if (!
client.IsAlive) return;
            if (
OnDisconnect != null)
                
OnDisconnect(client);
        }
    }

PHP Code:
using System;
using System.Net;
using System.Text;
using System.Linq;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace 
PureConquer.Network.ServerSocket
{
    public class 
Wrapper
    
{
        public 
Socket Socket get; private set; }
        public 
SocketServer Server get; private set; }
        public 
IPEndPoint RemoteEndPoint get; private set; }
        private 
readonly byte[] _buffer;
        public 
object Owner;
        public 
Boolean IsAlive get { return Socket.Connected; } }

        public 
String IP
        
{
            
get
            
{
                if (
Socket != null)
                    return (
Socket.RemoteEndPoint as IPEndPoint).Address.ToString();
                else
                    return 
null;
            }
        }

        public 
Wrapper(SocketServer serverSocket socketint bufferLength)
        {
            
Server server;
            
Socket socket;
            
_buffer = new byte[bufferLength];
            
RemoteEndPoint = (IPEndPoint)Socket.RemoteEndPoint;
            
Socket.NoDelay true;
        }

        public 
void BeginReceive()
        {
            try
            {
                
Socket.BeginReceive(_buffer0_buffer.LengthSocketFlags.None, new AsyncCallback(Receive), null);
            }
            catch (
SocketException)
            {
                
Server.InvokeOnDisconnect(this);
            }
        }
        private 
void Receive(IAsyncResult result)
        {
            if (
Socket != null)
            {
                try
                {
                    
SocketError error;
                    
int length Socket.EndReceive(resultout error);
                    if (
IsAlive && error == SocketError.Success)
                    {
                        if (
length 0)
                        {
                            try
                            {
                                
Server.InvokeOnReceive(_bufferlengththis);
                            }
                            catch (
Exception e)
                            {
                                
Console.WriteLine(e.ToString());
                            }
                            
finally
                            
{
                                
BeginReceive();
                            }
                        }
                        else
                        {
                            
Server.InvokeOnDisconnect(this);
                        }
                    }
                }
                catch (
SocketException)
                {
                    
Server.InvokeOnDisconnect(this);
                }
            }
        }

        public 
void Send(byte[] packet)
        {
            if (
IsAlive)
            {
                try
                {
                    
Socket.Send(packet0packet.LengthSocketFlags.None);
                }
                catch (
SocketException)
                {
                    
Server.InvokeOnDisconnect(this);
                }
            }
        }

        private 
void EndSend(IAsyncResult result)
        {
            try
            {
                
Socket.EndSend(result);
            }
            catch (
SocketException)
            {
                
Server.InvokeOnDisconnect(this);
            }
        }

        public 
void Disconnect()
        {
            try
            {
                
Socket.Disconnect(false);
            }
            catch (
SocketException)
            {
            }
            
Server.InvokeOnDisconnect(this);
        }

        public 
override string ToString()
        {
            return 
RemoteEndPoint.ToString();
        }
    }

05/18/2017 05:07 Spirited#4
Can you post more of the receive logic?
What's your client buffer length?
Do you have any parallelism outside of the async socket thread pool?
05/20/2017 23:49 iBotx#5
Quote:
Originally Posted by Spirited View Post
Can you post more of the receive logic?
PHP Code:
static void AuthServer_OnClientReceive(byte[] bufferWrapper arg3)
        {
            var 
player arg3.Connector as Client.AuthClient;
            
player.Cryptographer.Decrypt(bufferbuffer.Length);
            
player.Queue.Enqueue(bufferbuffer.Length);
            while (
player.Queue.CanDequeue())
            {
                
byte[] packet player.Queue.Dequeue();
                
ushort len BitConverter.ToUInt16(packet0);
                
ushort id BitConverter.ToUInt16(packet2);
                if (
len == 312)
                {
                    
player.Info MsgAccountSRP6Ex.Deserialize(packet);
                    
player.Account = new AccountTable(player.Info.Username);
                    if (!
player.Account.exists || (player.Account.exists && player.Account.Password != player.Info.Password))
                    {
                        
player.Send(MsgConnectEx.Rejected(MsgConnectEx.RejectionCode.InvalidInfo));
                        return;
                    }
                    if (
IPBan.IsBanned(arg3.Socket.IP) || player.Account.State == AccountTable.AccountState.Banned)
                    {
                        
player.Send(MsgConnectEx.Rejected(MsgConnectEx.RejectionCode.Banned));
                        return;
                    }
                    if (
player.Account.Password == player.Info.Password && player.Account.exists)
                    {
                        var 
idF player.Account.GenerateKey();
                        
Kernel.AwaitingPool[idF] = player.Account;
                        
player.Send(MsgConnectEx.Verified(idFProgram.GameIPProgram.GamePort));
                        return;
                    }
                }
            }
        }
        static 
void AuthServer_OnClientDisconnect(Wrapper obj)
        {
            
obj.Socket.Disconnect();
        }
        static 
void AuthServer_OnClientConnect(Wrapper obj)
        {
            
Client.AuthClient authState;
            
obj.Connector = (authState = new Client.AuthClient(obj.Socket));
            
authState.Cryptographer = new Network.Cryptography.AuthCryptography();
            
authState.Send(MsgEncryptCode.Login((uint)Kernel.Random.Next()));
        } 

Quote:
What's your client buffer length?
4048

Quote:
Do you have any parallelism outside of the async socket thread pool?
No
05/21/2017 00:14 JaniQ#6
I read somewhere that the socket system used in redux is flawed I don't know if you are using it or what's the problem with it since I didn't really touch it but yeah , you may want to use a different socket system or fix the flaws whatever they are.
05/21/2017 01:56 Spirited#7
Hard to say without walking the code. Those client queues are very suspicious to me.
What happens when you use the sockets from Phoenix only?
05/21/2017 02:19 pintinho12#8
Quote:
Originally Posted by Spirited View Post
Hard to say without walking the code. Those client queues are very suspicious to me.
What happens when you use the sockets from Phoenix only?
My server with Phoenix Socket never had RAM usage issues because of online players amount, it didn't change much from 0 to 100 players.
05/21/2017 17:09 KraHen#9
Yeah, that queue looks suspicious, also maybe if you are using unmanaged code in your cipher you might be leaking memory? These are just shots in the dark though.
05/21/2017 18:15 iBotx#10
Quote:
Originally Posted by KraHen View Post
Yeah, that queue looks suspicious, also maybe if you are using unmanaged code in your cipher you might be leaking memory? These are just shots in the dark though.
i'm using co2_core_dll of cptsky's and when i memory profiled it i saw that something called biginteger uses a huge memory but i think it's get collected by the GC, so i never bothered but idk honestly but reading the comments the socket system seems to be fine.