Register for your free account! | Forgot your password?

Go Back   elitepvpers > MMORPGs > Conquer Online 2 > CO2 Programming
You last visited: Today at 13:42

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



[Intermediate] - C# AsyncSockets(Client)

Discussion on [Intermediate] - C# AsyncSockets(Client) within the CO2 Programming forum part of the Conquer Online 2 category.

Reply
 
Old   #1
 
elite*gold: 20
Join Date: Aug 2005
Posts: 1,734
Received Thanks: 1,001
[Intermediate] - C# AsyncSockets(Client)

Hello everyone! This is my second tutorial I'll be writing on AsyncSockets and also the last one (I've then covered both Client/Server sides of it)

So lets start off with the tutorial

Requirements
- Microsoft Visual C# 2008 Express Edition
- .NET Framework 3.5

I'll be numbering the steps in my opinion it's alot easier to follow that way.


1. Start your Visual C# 2008 Express Edition and create a new project (File -> New Project -> Microsoft forms application) and name it.

2. Now you have to add a new class in this project (Project > Add class) Name it 'ClientSocket.cs' so it's easier to follow this tutorial.

3. Now the code should look something like this :
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace <YourNameSpace>
{
    class ClientSocket
    {
    }
}
4. Now we need to remove the namespace <name> { } so it can be accessed globally. Also we have to add a baseclass to handle the packets etc.
5. We also need to add the namespaces to beable to use sockets. The code should look like this after these steps.
Code:
using System;
using System.Net;
using System.Net.Sockets;

class BSocket
{

}
class ClientSocket
{

}
6. Alright now we need to add this to the top
Code:
using System.Runtime.InteropServices;
7. Now we need to make a new class to handle unsafe methods, I call the class Native. Add this to your project too
Code:
unsafe class Native
{
    [DllImport("msvcrt.dll")]
    public static extern void* memcpy(void* dest, void* src, uint size); 
}
8. You might have noticed that we can't compile it yet; Because of that unsafe.
9. We need to allow unsafe code in the project so go to Project > Properties > Build > Check the 'Allow unsafe code' box.
10. Now like on the ServerSocket part, we need to add the variables into BSocket class to handle all the information needed.
11. What we need is byte[] for buffer, int(s) for ID & BufferLength & a socket

12. The BSocket code should look like this :
Code:
class BSocket
{
    public BSocket(uint bSize)
    {
        Buffer = new byte[bSize];
    }
    public Socket wSocket;
    public int ID = -1,
               BufferLength = 0;
    public byte[] Buffer;
    public unsafe byte[] Packet
    {
        get
        {
            byte[] ret = new byte[BufferLength];
            fixed (byte* des = ret, src = Buffer)
                Native.memcpy(des, src, (uint)BufferLength);
            return ret;
        }
    }
}
13. Now we need to add delegates into the project so we can make our custom events (OnClientConnect, OnReceivePacket etc)

14. Add this code after the BSocket but before ClientSocket
Code:
delegate void SocketEvent(object Sender, BSocket Socket);
delegate void SocketErrorEvent(object Sender, BSocket Socket, string Error);
15. The code should look like this now :
Code:
delegate void SocketEvent(object Sender, BSocket Socket);
delegate void SocketErrorEvent(object Sender, BSocket Socket, string Error);
class ClientSocket
{

}
16. Now we need to add the actual events, so add this code inside your ClientSocket class
Code:
public event SocketEvent OnClientConnect,
                             OnReceivePacket;
public event SocketErrorEvent OnClientError;
17. Now we need to add instance of BSocket in it so add this to code (inside ClientSocket class) :
Code:
private BSocket Socket;
18. Now we need to add a method that takes the IP and Port as params for example like this :
Code:
 public void Connect(string IP, ushort Port)
    {
        if (IP == "" || Port == 0)
            return;
        Socket = new BSocket(0xFFFF);
        Socket.wSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPAddress RemoteIP;
        if (!IPAddress.TryParse(IP, out RemoteIP))
            return;
        Socket.wSocket.BeginConnect(RemoteIP, Port, new AsyncCallback(Connecting), Socket);
    }
19. Now as you can see, the method will stop executin on following things, IP is a null string, or Port is 0. A little bit lower there is that part where it parses the ip into IPAddress, if it fails to do that (Invalid ip) It'll stop executing the method.

20. Now we need to add a method for that AsyncCall back 'Connecting'. So add this to your code
Code:
private void Connecting(IAsyncResult res)
    {
        BSocket Sckt = (BSocket)res.AsyncState;
        try
        {
            Sckt.wSocket.EndConnect(res);
            if (OnClientConnect != null)
                OnClientConnect(this, Sckt);
            Sckt.wSocket.BeginReceive(Sckt.Buffer, 0, 0xFFFF, SocketFlags.None, new AsyncCallback(ReceivePacket), Sckt);
        }
        catch (Exception e)
        {
            if (OnClientError != null)
                OnClientError(this, Sckt, e.Message);
        }
    }
21. This basically triggers the OnClientConnect event, will explain this later on : how to use it.

22. Now we need to add a ReceivePacket method so add this to your code
Code:
private void ReceivePacket(IAsyncResult res)
    {
        BSocket Sckt = (BSocket)res.AsyncState;
        try
        {
            SocketError Error;
            Sckt.BufferLength = Sckt.wSocket.EndReceive(res, out Error);
            if (Error == SocketError.Success && Sckt.BufferLength > 0)
            {
                if (OnReceivePacket != null)
                    OnReceivePacket(this, Sckt);
                Sckt.wSocket.BeginReceive(Sckt.Buffer, 0, 0xFFFF, SocketFlags.None, new AsyncCallback(ReceivePacket), Sckt);
            }
        }
        catch (Exception e)
        {
            if (OnClientError != null)
                OnClientError(this, Sckt, e.Message);
        }
    }
23. We still need to add a method to send bytes. So add this to your code

Code:
 public void Send(byte[] Packet)
    {
        if (Socket.wSocket.Connected)
            Socket.wSocket.Send(Packet);
    }
24. It'll send the bytes only if the Socket is connected somewhere. Now the final code should look like this
Code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

unsafe class Native
{
    [DllImport("msvcrt.dll")]
    public static extern void* memcpy(void* dest, void* src, uint size); 
}
class BSocket
{
    public BSocket(uint bSize)
    {
        Buffer = new byte[bSize];
    }
    public Socket wSocket;
    public int ID = -1,
               BufferLength = 0;
    public byte[] Buffer;
    public unsafe byte[] Packet
    {
        get
        {
            byte[] ret = new byte[BufferLength];
            fixed (byte* des = ret, src = Buffer)
                Native.memcpy(des, src, (uint)BufferLength);
            return ret;
        }
    }
}
delegate void SocketEvent(object Sender, BSocket Socket);
delegate void SocketErrorEvent(object Sender, BSocket Socket, string Error);
class ClientSocket
{
    public event SocketEvent OnClientConnect,
                             OnReceivePacket;
    public event SocketErrorEvent OnClientError;

    private BSocket Socket;

    public void Connect(string IP, ushort Port)
    {
        if (IP == "" || Port == 0)
            return;
        Socket = new BSocket(0xFFFF);
        Socket.wSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPAddress RemoteIP;
        if (!IPAddress.TryParse(IP, out RemoteIP))
            return;
        Socket.wSocket.BeginConnect(RemoteIP, Port, new AsyncCallback(Connecting), Socket);
    }
    public void Send(byte[] Packet)
    {
        if (Socket.wSocket.Connected)
            Socket.wSocket.Send(Packet);
    }
    private void Connecting(IAsyncResult res)
    {
        BSocket Sckt = (BSocket)res.AsyncState;
        try
        {
            Sckt.wSocket.EndConnect(res);
            if (OnClientConnect != null)
                OnClientConnect(this, Sckt);
            Sckt.wSocket.BeginReceive(Sckt.Buffer, 0, 0xFFFF, SocketFlags.None, new AsyncCallback(ReceivePacket), Sckt);
        }
        catch (Exception e)
        {
            if (OnClientError != null)
                OnClientError(this, Sckt, e.Message);
        }
    }
    private void ReceivePacket(IAsyncResult res)
    {
        BSocket Sckt = (BSocket)res.AsyncState;
        try
        {
            SocketError Error;
            Sckt.BufferLength = Sckt.wSocket.EndReceive(res, out Error);
            if (Error == SocketError.Success && Sckt.BufferLength > 0)
            {
                if (OnReceivePacket != null)
                    OnReceivePacket(this, Sckt);
                Sckt.wSocket.BeginReceive(Sckt.Buffer, 0, 0xFFFF, SocketFlags.None, new AsyncCallback(ReceivePacket), Sckt);
            }
        }
        catch (Exception e)
        {
            if (OnClientError != null)
                OnClientError(this, Sckt, e.Message);
        }
    }
}
25. Now you can go to your Form and test this code. This is example how I tested it

Code:
public Form1()
        {
            InitializeComponent();
            ClientSocket ClientSocket = new ClientSocket();
            ClientSocket.Connect("127.0.0.1", 9958);
            ClientSocket.OnClientError += new SocketErrorEvent(ClientSocket_OnClientError);
            ClientSocket.OnClientConnect += new SocketEvent(ClientSocket_OnClientConnect);
            ClientSocket.OnReceivePacket += new SocketEvent(ClientSocket_OnReceivePacket);
        }

        void ClientSocket_OnReceivePacket(object Sender, BSocket Socket)
        {
            MessageBox.Show("We go a packet");
        }

        void ClientSocket_OnClientConnect(object Sender, BSocket Socket)
        {
            MessageBox.Show("Wohoo, we connected succesfully!");
        }

        void ClientSocket_OnClientError(object Sender, BSocket Socket, string Error)
        {
            MessageBox.Show(Error);
        }
Now if you have any questions about the code or I made a mistake somewhere, please tell me.
tanelipe is offline  
Thanks
8 Users
Old 08/17/2008, 14:55   #2
 
© Haydz's Avatar
 
elite*gold: 20
Join Date: Jan 2008
Posts: 1,042
Received Thanks: 252
Once Again Very Good Tutorial
© Haydz is offline  
Old 08/18/2008, 06:55   #3
 
elite*gold: 0
Join Date: May 2007
Posts: 15
Received Thanks: 3
what is this i dont understand it will make soc ur items or nothing just a name name
joven3000 is offline  
Old 08/18/2008, 07:53   #4
 
Hiyoal's Avatar
 
elite*gold: 20
Join Date: Mar 2007
Posts: 2,444
Received Thanks: 1,067
Lol, Search Sockets on google. This has nothing to do with Conquer.

Hiyoal
Hiyoal is offline  
Old 08/18/2008, 10:14   #5
 
elite*gold: 20
Join Date: Aug 2005
Posts: 1,734
Received Thanks: 1,001
Wikipedia :

Quote:
An Internet socket (or commonly, a network socket or socket), is an end-point of a bidirectional process-to-process communication flow across an IP based network, such as the Internet. Each socket is mapped to an application process or thread. A socket is an interface between an application process or thread and the TCP/IP protocol stack provided by the operating system.
:

Quote:
When using non-blocking sockets, you have to continually poll the socket to see whether or not you have any actions that need to be performed. These actions can include sending and receiving data, establishing a connection, sending back a response to a connection request, etc. Non-blocking sockets have the advantage in that they allow normal program execution to continue – meaning you can process data while waiting for more to come in. This immediately makes them superior to blocking sockets in many cases (but not all).

However, asynchronous sockets take polling to a new level – they do it for you. This means that you can focus on other things while WinSock keeps watch over your sockets. (Sounds better than non-blocking sockets eh? Not always, as you’ll soon see.)
So, basically async sockets do not freeze the thread (a.k.a you can continue doing what ever you want). Sync sockets freezes the thread (Well, wait for incoming data etc)
tanelipe is offline  
Old 08/18/2008, 12:20   #6
 
elite*gold: 20
Join Date: Mar 2005
Posts: 1,248
Received Thanks: 2,252
:/ Its a good tutorial, but I rather use blocking sockets, to wait until a packet is received, then continue parsing the packet.. but do nothing until that. You can create other threads to handle everything you need done, while the 2 recv threads are working (and blocking if packets are coming in slower.... lol)
XtremeX-CO is offline  
Old 09/01/2008, 16:53   #7
 
Tw3ak's Avatar
 
elite*gold: 20
Join Date: Jun 2005
Posts: 1,489
Received Thanks: 301
Quote:
Originally Posted by XtremeX-CO View Post
:/ Its a good tutorial, but I rather use blocking sockets, to wait until a packet is received, then continue parsing the packet.. but do nothing until that. You can create other threads to handle everything you need done, while the 2 recv threads are working (and blocking if packets are coming in slower.... lol)
That is the problem with the existing Private co sources,You don't want to use blocking as it freezes up the server threads and fubards the stability in connections ending up in complete server crashes.

You want to use AsyncSockets and have proper checking and error handling,Not just assume all the data being sent/received is correct resulting in malformed packets and possible race conditions.
Tw3ak is offline  
Old 09/02/2008, 03:01   #8
 
elite*gold: 20
Join Date: Mar 2005
Posts: 1,248
Received Thanks: 2,252
Quote:
Originally Posted by Tw3ak View Post
That is the problem with the existing Private co sources,You don't want to use blocking as it freezes up the server threads and fubards the stability in connections ending up in complete server crashes.

You want to use AsyncSockets and have proper checking and error handling,Not just assume all the data being sent/received is correct resulting in malformed packets and possible race conditions.
Yeah I havent really used non blocking sockets that much, but it all depends on the application. I really need to study more
XtremeX-CO is offline  
Reply


Similar Threads Similar Threads
[Intermediate]Server basics
05/28/2020 - CO2 Programming - 31 Replies
Hello elitepvpers members! In this topic, i will try to explain the basics of creating a conquer online private server from 'scratch' :} Before reading this i would suggest that you have to read these threads: http://www.elitepvpers.com/forum/co2-pserver-discu ssions-questions/177002-ask-yourself-before-you-st art-trying-make-server.html http://www.elitepvpers.com/forum/co2-programming/1 59269-intermediate-c-asyncsockets-server.html
[Intermediate] - C# AsyncSockets(Server)
11/07/2010 - CO2 Programming - 16 Replies
Hello everyone! In this tutorial I will teach you how to do simple ServerSocket and ClientSocket implementation using Asynchronous Sockets (non blocking, doesn't wait for data & doesn't freeze the current thread) Requirement(s) - Microsoft Visual C# 2008 Express Edition - .NET Framework 3.5 (I'm not sure wether this comes with the above program or not.) I will be using that program on all my C# tutorials so get ready to download it. :D I'll start off with Async ServerSocket; I'll...
[Tips][Intermediate]Making A UCE
07/07/2009 - Grand Chase Philippines - 11 Replies
How To Make A UCE Requirement : At least Intemediate Hacking Brains ;) Content Page: (Note that you could just press "Ctrl + F" to enable the "Find" function if you want to quickly move to a specific steps.) A_1) Updates of tutorial B_2) Programmes required



All times are GMT +1. The time now is 13:42.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.