[Release]Async Sockets (No packet-splitter)

09/18/2012 22:05 I don't have a username#1
So after seeing this thread: [Only registered and activated users can see links. Click Here To Register...]

I thought I'd make some socket server that could handle the packets without needing to split.

Source:

Example usage:

Server:

Client:

I hope you'll find this useful :)

Enjoy! :D
09/19/2012 00:05 go for it#2
im so damn thankful :D this is inspiring XD
09/19/2012 00:55 InfamousNoone#3
You may have tested this on a private server and had success, but I noticed one thing in your receive body (as well as your receive header) part which will fail in a proxy environment. You may the assumption when you say "I want to receive n-bytes" you receive n-bytes, and if you don't, you drop the connection. In the real world however, fragmentation occurs and you may only receive a fraction of a n-bytes and may need to continue receiving until n-bytes has been read in total.
09/19/2012 01:07 I don't have a username#4
Quote:
Originally Posted by InfamousNoone View Post
You may have tested this on a private server and had success, but I noticed one thing in your receive body (as well as your receive header) part which will fail in a proxy environment. You may the assumption when you say "I want to receive n-bytes" you receive n-bytes, and if you don't, you drop the connection. In the real world however, fragmentation occurs and you may only receive a fraction of a n-bytes and may need to continue receiving until n-bytes has been read in total.
Ohh yeah I didn't think of that! I'll update this tomorrow also found a few other things to change :p
09/19/2012 02:11 Danial Eugen#5
Amazing work i was arranging a guide for that xD but you did :P.

Really nice code.

But in DataPacket.cs why don't you just turn the buffer to read only and rename it
Code:
        private readonly byte[] _buffer;
To prevent using this. redundantly ?

Code:
        public DataPacket(byte[] buffer)
        {
            this.buffer = new byte[buffer.Length];
            System.Buffer.BlockCopy(buffer, 0, this.buffer, 0, buffer.Length);
        }
It is really misleading to have 2 byte[] with the same name.

Also i see you never used this name spaces
Code:
using System;
using System.Collections.Generic;
using System.Linq;
See this edited DataPacket.cs
09/19/2012 02:34 I don't have a username#6
Let me break this down to you.

Quote:
Originally Posted by Danial Eugen View Post
that xD but you did :P.

Really nice code.

But in DataPacket.cs why don't you just turn the buffer to read only and rename it
Code:
        private readonly byte[] _buffer;
To prevent using this. redundantly ?

Code:
        public DataPacket(byte[] buffer)
        {
            this.buffer = new byte[buffer.Length];
            System.Buffer.BlockCopy(buffer, 0, this.buffer, 0, buffer.Length);
        }
It is really misleading to have 2 byte[] with the same name.
Felt lazy and the datapacket is just a class I'm using over and over and never really modifying it. Hence why it's not commented or documented at all.

Quote:
Originally Posted by Danial Eugen View Post
Also i see you never used this name spaces
Code:
using System;
using System.Collections.Generic;
using System.Linq;
I'm not wasting my time removing namespaces that I don't use and as I can't remember the short key for it then as lazy as I am I'll just leave them and the System namespace is always in use lol, so it'd be Collections.Generic and Linq only.

Some more constructive feed back would be nice instead this...
09/19/2012 02:48 Danial Eugen#7
Quote:
Originally Posted by I don't have a username View Post
Let me break this down to you.



Felt lazy and the datapacket is just a class I'm using over and over and never really modifying it. Hence why it's not commented or documented at all.



I'm not wasting my time removing namespaces that I don't use and as I can't remember the short key for it then as lazy as I am I'll just leave them and the System namespace is always in use lol, so it'd be Collections.Generic and Linq only.

Some more constructive feed back would be nice instead this...
Well you find this non constructive :D

i was just pointing you out because i wanted your code to be elegant and clean :D;However, i see your code perfect and doing the job...

Also in DataPacket you don't have to add using System;, simply because you only needed it 2 time but you just added System before the code

Like
Code:
System.Buffer.BlockCopy(buffer, 0, _buffer, 0, buffer.Length);
Also can i use your Method of writing and reading (DataPacket.cs) the packets in my -non conquer related- project ? it will save me sometime writing one :D
09/19/2012 03:29 I don't have a username#8
Quote:
Originally Posted by Danial Eugen View Post
Well you find this non constructive :D

i was just pointing you out because i wanted your code to be elegant and clean :D;However, i see your code perfect and doing the job...

Also in DataPacket you don't have to add using System;, simply because you only needed it 2 time but you just added System before the code

Like
Code:
System.Buffer.BlockCopy(buffer, 0, _buffer, 0, buffer.Length);
Also can i use your Method of writing and reading (DataPacket.cs) the packets in my -non conquer related- project ? it will save me sometime writing one :D
I like to type the whole namespace out for System.Buffer. Most likely a personal preference and yes you can lol it's not like it's anything special.
09/19/2012 03:36 Danial Eugen#9
hehe :D i thought you used `System.Buffer` because if you turned it to Buffer it will conflict with
Code:
        protected byte[] Buffer
        {
            get
            {
                return _buffer;
            }
        }
09/19/2012 03:52 I don't have a username#10
Quote:
Originally Posted by Danial Eugen View Post
hehe :D i thought you used `System.Buffer` because if you turned it to Buffer it will conflict with
Code:
        protected byte[] Buffer
        {
            get
            {
                return _buffer;
            }
        }
Even if it didn't then I'd still have typed it out.
09/19/2012 23:40 go for it#11
i've had some hard time understanding IAsyncResult and call backs , so i did search
and here what i found out (i did fully understand it as it was explained in pretty easy way and WAY BETTER than msdn ) so im sharing them for everyone
Quote:
The IAsyncResult interface represents an operation (such as a web request or a database call) that is running in the background, while your code continues to execute. It can tell you whether the operation finished (the IsCompleted property). It also gives you a WaitHandle object (the AsyncWaitHandle property) which can be used to wait until the operation finishes. (By calling result.AsyncWaitHandle.WaitOne())

You get an IAsyncResult by calling a BeginWhatever method. (BeginExecuteReader, BeginGetResponse, and many others). The BeginWhatever method will take any parameters needed for the operation (For example, BeginExecuteReader can take a CommandBehavior parameter), and can take an AsyncCallback delegate (not interface) and a state parameter. In returns an IAsyncResult object.

The AsyncCallback delegate is a method that you supply, which will be called when the operation finishes. It will usually be called on a different thread, so be careful in it. Your AsyncCallback method will be given the same IAsyncResult that the BeginWhatever method gave you earlier. The state parameter is put into the IAsyncResult and ignored by the system; you can use it in your AsyncCallback method to keep track of what the operation was for. (The state can be whatever you want it to be, including null)

Inside your AsyncCallback (or anywhere else), you can call the EndWhatever method that corresponds to the BeginWhatever method you called in the first place. You have to give it the IAsyncResult from BeginWhatever or from the AsyncCallback. When you call it, it will wait for the operation to finish (if it isn't already finished), and then give you back the operation's result. (Assuming the operation returns something; for example, WebRequest.EndGetResponse will return a WebResponse). If any error occurred during the operation, EndWhatever will throw an exception.
Quote:
A common use of internal access is in component-based development because it enables a group of components to cooperate in a private manner without being exposed to the rest of the application code. For example, a framework for building graphical user interfaces could provide Control and Form classes that cooperate using members with internal access. Since these members are internal, they are not exposed to code that is using the framework.
Quote:
EndAccept completes a call to BeginAccept. Before calling BeginAccept, you need to create a callback method that implements the AsyncCallback delegate. This callback method executes in a separate thread, and is called by the system after the BeginAccept method returns. It must accept the asyncResult parameter returned from the BeginAccept method.

Within the callback method, call the AsyncState method of the asyncResult parameter to obtain the Socket on which the connection attempt is being made. After obtaining the Socket, you can call the EndAccept method to successfully complete the connection attempt.

The EndAccept method blocks until a connection is pending in the incoming connection queue. The EndAccept method accepts the incoming connection and returns a new Socket that can be used to send data to and receive data from the remote host.
Quote:
The EndReceive method completes the asynchronous read operation started in the BeginReceive method.

Before calling BeginReceive, you need to create a callback method that implements the AsyncCallback delegate. This callback method executes in a separate thread and is called by the system after BeginReceive returns. The callback method must accept the IAsyncResult returned by the BeginReceive method as a parameter.

Within the callback method, call the AsyncState method of the IAsyncResult to obtain the state object passed to the BeginReceive method. Extract the receiving Socket from this state object. After obtaining the Socket, you can call the EndReceive method to successfully complete the read operation and return the number of bytes read.

The EndReceive method will block until data is available. If you are using a connectionless protocol, EndReceive will read the first enqueued datagram available in the incoming network buffer. If you are using a connection-oriented protocol, the EndReceive method will read as much data as is available up to the number of bytes you specified in the size parameter of the BeginReceive method. If the remote host shuts down the Socket connection with the Shutdown method, and all available data has been received, the EndReceive method will complete immediately and return zero bytes.

To obtain the received data, call the AsyncState method of the IAsyncResult, and extract the buffer contained in the resulting state object.

To cancel a pending BeginReceive, call the Close method.
Quote:
The Monitor class controls access to objects by granting a lock for an object to a single thread. Object locks provide the ability to restrict access to a block of code, commonly called a critical section. While a thread owns the lock for an object, no other thread can acquire that lock. You can also use Monitor to ensure that no other thread is allowed to access a section of application code being executed by the lock owner, unless the other thread is executing the code using a different locked object.

Monitor.TryEnter(Object, int32) Attempts to acquire an exclusive lock on the specified object, and atomically sets a value that indicates whether the lock was taken.

Monitor.Exit Releases an exclusive lock on the specified object.


i took those form msdn as those what jacob used at this example , one does the look for 50 ms which is enough to try sending the packet and one release the lock so the next buffer could use baseSocket.BeginSend

check out [Only registered and activated users can see links. Click Here To Register...] for more
i duno why i find this better than locks >.<
to be edited if i found another method/interface that i can't understand and found good explanation for it around
so far i've mentioned iasyncresult , internal and socket endaccept , and yes im going in sequence as im reading it (also doing a flow chart with methods on sketch to fully understand the logic and how the system work)
btw most of information i post and explanation is from stackoverflow and msdn


---------------------------------------------------------------------------------------------
hybrid i got question about
Quote:
You may have tested this on a private server and had success, but I noticed one thing in your receive body (as well as your receive header) part which will fail in a proxy environment. You may the assumption when you say "I want to receive n-bytes" you receive n-bytes, and if you don't, you drop the connection. In the real world however, fragmentation occurs and you may only receive a fraction of a n-bytes and may need to continue receiving until n-bytes has been read in total.
thanks for this information , but i got a question , i should not disconnect if i didn't receive the size of packet i read on the header , i should continue receiving until i get that n-bytes , so they may get delayed but server must send it , right ?
----------------------------------------------------------------------------------------------
jacob :D i've been 19 hrs learning from this and i enjoyed it and the logic , also it improved my programming skills :D was damn confusing until i made something crazy which u may scream my face off for :D :D
here
09/20/2012 16:44 InfamousNoone#12
Quote:
Originally Posted by go for it View Post
---------------------------------------------------------------------------------------------
hybrid i got question about

thanks for this information , but i got a question , i should not disconnect if i didn't receive the size of packet i read on the header , i should continue receiving until i get that n-bytes , so they may get delayed but server must send it , right ?
Typically, you may not receive the entire packet at the same time this occurs to fragmentation. So, your code becomes circular until nBytes has been received like this (I haven't actually tested it, but it should give you a fairly good idea of what I mean by circular):

Code:
    public class ReceiveAsyncBuffer
    {
        public bool OperationInProgress { get; private set; }
        public byte[] Buffer { get; private set; }
        public int Received { get { return offset; } }

        private Socket target;
        private int offset;
        private int left;
        private Action<bool> callback;

        public ReceiveAsyncBuffer(int size)
        {
            Buffer = new byte[size];
        }
        public void Receive(Socket socket, int size, Action<bool> complete)
        {
            if (OperationInProgress)
                throw new InvalidOperationException("another receive operation is already in progress");
            if (complete == null)
                throw new ArgumentNullException("complete delegate cannot be null");

            this.target = socket;
            this.offset = 0;
            this.left = size;
            this.callback = complete;
            this.OperationInProgress = true;

            this.BlockReceive();
        }
        private void BlockReceive()
        {
            try
            {
                this.target.BeginReceive(this.Buffer, this.offset, this.left, SocketFlags.None,
                    (result) =>
                    {
                        try
                        {
                            int nRecv = this.target.EndReceive(result);
                            if (nRecv <= 0)
                            {
                                this.OperationInProgress = false;
                                this.callback(false); // fail
                            }
                            else
                            {
                                this.left -= nRecv;
                                this.offset += nRecv;
                                if (this.left == 0)
                                {
                                    this.OperationInProgress = false;
                                    this.callback(true); // done
                                }
                                else
                                    BlockReceive();
                            }

                        }
                        catch (Exception)
                        {
                            this.OperationInProgress = false;
                            this.callback(false);
                        }

                    }, null);
            }
            catch (Exception)
            {
                this.OperationInProgress = false;
                this.callback(false); // failed
            }
        }
    }
09/20/2012 17:35 I don't have a username#13
As I got quite busy yesterday with my presentation for exam which I had today and haven't got the time rewrite it then I'll eventually do it today I think :p
09/20/2012 17:45 Danial Eugen#14
Quote:
Originally Posted by I don't have a username View Post
As I got quite busy yesterday with my presentation for exam which I had today and haven't got the time rewrite it then I'll eventually do it today I think :p
How was your exam :P
09/20/2012 19:03 I don't have a username#15
Quote:
Originally Posted by Danial Eugen View Post
How was your exam :P
Graduated with an A :D