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 :
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.
6. Alright now we need to add this to the top
7. Now we need to make a new class to handle unsafe methods, I call the class Native. Add this to your project too
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 :
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
15. The code should look like this now :
16. Now we need to add the actual events, so add this code inside your ClientSocket class
17. Now we need to add instance of BSocket in it so add this to code (inside ClientSocket class) :
18. Now we need to add a method that takes the IP and Port as params for example like this :
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
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
23. We still need to add a method to send bytes. So add this to your code
24. It'll send the bytes only if the Socket is connected somewhere. Now the final code should look like this
25. Now you can go to your Form and test this code. This is example how I tested it
Now if you have any questions about the code or I made a mistake somewhere, please tell me.
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
{
}
}
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
{
}
Code:
using System.Runtime.InteropServices;
Code:
unsafe class Native
{
[DllImport("msvcrt.dll")]
public static extern void* memcpy(void* dest, void* src, uint size);
}
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;
}
}
}
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);
Code:
delegate void SocketEvent(object Sender, BSocket Socket);
delegate void SocketErrorEvent(object Sender, BSocket Socket, string Error);
class ClientSocket
{
}
Code:
public event SocketEvent OnClientConnect,
OnReceivePacket;
public event SocketErrorEvent OnClientError;
Code:
private BSocket Socket;
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);
}
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);
}
}
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);
}
}
Code:
public void Send(byte[] Packet)
{
if (Socket.wSocket.Connected)
Socket.wSocket.Send(Packet);
}
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);
}
}
}
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);
}