In Your .h File
#define RECEIVE_BUFFER_SIZE 1500
private: Socket ^serverSocket;
//-------------------------------------
//----- CLASS FOR RECEIVE SOCKETS -----
//-------------------------------------
ref class StateObject
{
public:
property int bufSize;
property Socket ^workSocket;
property array<unsigned char>^ message;
StateObject(Socket^ sock, int bufsize)
{
workSocket = sock;
bufSize = bufsize;
message = gcnew array<unsigned char>(bufsize);
}
};
Create Socket
//----- SETUP UDP ASYNCHRONOUS RECEIVE ----- try { //----- CREATE UDP SOCKET AND BIND TO LOCAL PORT ----- serverSocket = gcnew Socket(AddressFamily::InterNetwork, SocketType::Dgram, ProtocolType::Udp); IPEndPoint ^ipEndPoint = gcnew IPEndPoint(IPAddress::Any, LOCAL_UDP_SOCKET); //Assign the any IP of the machine and listen on port number serverSocket->Bind(ipEndPoint); //Bind required if not sending data (sending does bind for you) //----- CREATE ASYNCHRONOUS RECEIVE HANDLER -----
myClassNameIPEndPoint ^ipeSender1 = gcnew IPEndPoint(IPAddress::Any, 0); EndPoint ^epSender1 = (EndPoint^)(ipeSender1); //The epSender identifies the incoming clients StateObject ^so1 = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE); //Start reciving data using BeginReceiveFrom //(Use BeginReceiveFrom not BeginReceive so we can determin the sender when we receive a packet - only way when using UDP. If you don't care who the sender is you could use BeginReceive if you wanted, but no particular reason you need to) serverSocket->BeginReceiveFrom (so1->message, 0, so1->bufSize, //Byte array to store received data, offset into the buffer to start sotring the data, number of bytes to receive, SocketFlags::None, epSender1, //bitwise combination of the SocketFlags values, EndPoint that represents the source of the data. gcnew AsyncCallback(this, &myClassName::ReceiveCallback), so1); //AsyncCallback delegate, object containing state information for this request //UDP will also drop packets upon receipt if, even momentarily, BeginReceiveFrom is not active on the socket. //There is a short time between acceptance of a packet and calling another BeginReceiveFrom. Even if this call were the first one in MessageReceivedCallback, there's a //still short period when the app isn't listening. A simple solution is to activate several instances of BeginReceiveFrom, each with a separate buffer to hold received //packets. //CREATE ANOTHER ASYNCHRONOUS RECEIVE HANDLER IPEndPoint^ ipeSender2 = gcnew IPEndPoint(IPAddress::Any, 0); EndPoint^ epSender2 = (EndPoint^)(ipeSender2); StateObject^ so2 = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE); serverSocket->BeginReceiveFrom (so2->message, 0, so2->bufSize, SocketFlags::None, epSender2, gcnew AsyncCallback(this, &myClassName::ReceiveCallback), so2); //CREATE ANOTHER ASYNCHRONOUS RECEIVE HANDLER IPEndPoint^ ipeSender3 = gcnew IPEndPoint(IPAddress::Any, 0); EndPoint^ epSender3 = (EndPoint^)(ipeSender3); StateObject^ so3 = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE); serverSocket->BeginReceiveFrom (so3->message, 0, so3->bufSize, SocketFlags::None, epSender3, gcnew AsyncCallback(this, &myClassName::ReceiveCallback), so3); //CREATE ANOTHER ASYNCHRONOUS RECEIVE HANDLER IPEndPoint^ ipeSender4 = gcnew IPEndPoint(IPAddress::Any, 0); EndPoint^ epSender4 = (EndPoint^)(ipeSender4); StateObject^ so4 = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE); serverSocket->BeginReceiveFrom (so4->message, 0, so4->bufSize, SocketFlags::None, epSender4, gcnew AsyncCallback(this, &myClassName::ReceiveCallback), so4); //CREATE ANOTHER ASYNCHRONOUS RECEIVE HANDLER IPEndPoint^ ipeSender5 = gcnew IPEndPoint(IPAddress::Any, 0); EndPoint^ epSender5 = (EndPoint^)(ipeSender5); StateObject^ so5 = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE); serverSocket->BeginReceiveFrom (so5->message, 0, so5->bufSize, SocketFlags::None, epSender5, gcnew AsyncCallback(this, &myClassName::ReceiveCallback), so5); //CREATE ANOTHER ASYNCHRONOUS RECEIVE HANDLER IPEndPoint^ ipeSender6 = gcnew IPEndPoint(IPAddress::Any, 0); EndPoint^ epSender6 = (EndPoint^)(ipeSender6); StateObject^ so6 = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE); serverSocket->BeginReceiveFrom (so6->message, 0, so6->bufSize, SocketFlags::None, epSender6, gcnew AsyncCallback(this, &myClassName::ReceiveCallback), so6); //CREATE ANOTHER ASYNCHRONOUS RECEIVE HANDLER IPEndPoint^ ipeSender7 = gcnew IPEndPoint(IPAddress::Any, 0); EndPoint^ epSender7 = (EndPoint^)(ipeSender7); StateObject^ so7 = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE); serverSocket->BeginReceiveFrom (so7->message, 0, so7->bufSize, SocketFlags::None, epSender7, gcnew AsyncCallback(this, &myClassName::ReceiveCallback), so7); //CREATE ANOTHER ASYNCHRONOUS RECEIVE HANDLER IPEndPoint^ ipeSender8 = gcnew IPEndPoint(IPAddress::Any, 0); EndPoint^ epSender8 = (EndPoint^)(ipeSender8); StateObject^ so8 = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE); serverSocket->BeginReceiveFrom (so8->message, 0, so8->bufSize, SocketFlags::None, epSender8, gcnew AsyncCallback(this, &myClassName::ReceiveCallback), so8); } catch (Exception ^e) { }
Receive Handler
//*********************************
//*********************************
//********** UDP RECEIVE **********
//*********************************
//*********************************
void myClassName::ReceiveCallback(System::IAsyncResult^ iar)
{
int byteId;
UInt16 OpCode;
String ^RxFromIp;
UInt16 RxFromPort;
int ReTries;
StateObject^ so = (StateObject^)iar->AsyncState;
Socket^ client = so->workSocket;
//-----------------------------------
//----- PROCESS RECEIVED PACKET -----
//-----------------------------------
try
{
//Create a temporary EndPoint to pass to EndReceiveFrom (we have to do this to be able to get the RemoteEndPoint information - only way when using UDP)
IPEndPoint^ sender = gcnew IPEndPoint( IPAddress::Any,0 );
EndPoint^ tempRemoteEP = safe_cast<EndPoint^>(sender);
int rcv;
if ((rcv = client->EndReceiveFrom(iar, tempRemoteEP )) > 0) //Complete BeginReceive operation and get the message
{
byteId = 0;
if (
(so->message[byteId++] == 'H') &&
(so->message[byteId++] == 'e') &&
(so->message[byteId++] == 'l') &&
(so->message[byteId++] == 'l') &&
(so->message[byteId++] == 'o')
)
{
//------------------------
//----- VALID PACKET -----
//------------------------
//Get OpCode
OpCode = Convert::ToInt32(so->message[byteId++]) << 8;
OpCode |= Convert::ToInt32(so->message[byteId++]);
//----- GET SENDERS IP ADDRESS -----
SocketAddress^ remoteDeviceAddress = tempRemoteEP->Serialize();
if (remoteDeviceAddress->Family == AddressFamily::InterNetwork)
{
//IPv4 Address
RxFromPort = Convert::ToUInt16(remoteDeviceAddress[2]) << 8; //Port number is in bytes 2:3
RxFromPort |= Convert::ToUInt16(remoteDeviceAddress[3]);
RxFromIp = remoteDeviceAddress[4] + "." + remoteDeviceAddress[5] + "." + remoteDeviceAddress[6] + "." + remoteDeviceAddress[7]; //IP Address in bytes 4:7
}
//else if (remoteDeviceAddress->Family == AddressFamily::InterNetworkV6)
//{
// //IPv6 Address
//}
else
{
RxFromIp = "0.0.0.0";
OpCode = 0; //Dump the packet
}
switch (OpCode)
{
case 0x1234:
//-----------------------
//-----------------------
//----- OPCODE 1234 -----
//-----------------------
//-----------------------
SomeVariable = Convert::ToInt32(so->message[byteId++]) << 8;
SomeVariable |= Convert::ToInt32(so->message[byteId++]);
SomeString = Convert::ToString(so->message[byteId++]) + ".";
SomeString += Convert::ToString(so->message[byteId++]) + ".";
SomeString += Convert::ToString(so->message[byteId++]) + ".";
SomeString += Convert::ToString(so->message[byteId++]);
break;
} //switch (OpCode)
}
}
}
catch (Exception ^e)
{
}
finally
{
//----------------------------------
//----- SETUP FOR NEXT RECEIVE -----
//----------------------------------
ReTries = 50; //Limit the while loop just in case
while (ReTries) //We use a while loop as BeginReceiveFrom can occasionally cause a SocketException error when there is lots of receive activity. Without this the BeginReceiveFrom is lost causing no receive anymore once they are all used up.
{
ReTries--;
try
{
//----- CREATE ANOTHER ASYNCHRONOUS RECEIVE HANDLER TO REPLACE THIS ONE JUST USED -----
IPEndPoint^ ipeSender = gcnew IPEndPoint(IPAddress::Any, 0);
EndPoint^ epSender = (EndPoint^)(ipeSender); //The epSender identifies the incoming clients
so = gcnew StateObject(serverSocket, RECEIVE_BUFFER_SIZE);
serverSocket->BeginReceiveFrom (so->message, 0, so->bufSize, //Byte array to store received data, offset into the buffer to start sotring the data, number of bytes to receive,
SocketFlags::None, epSender, //bitwise combination of the SocketFlags values, EndPoint that represents the source of the data.
gcnew AsyncCallback(this, &DibbaReaders::ReceiveCallback), so); //AsyncCallback delegate, object containing state information for this request
ReTries = 0;
}
catch (Exception ^)
{
}
}
}
}
Transmit Packet From Server Socket
IPAddress ^address;
int byteId;
array<Byte>^sendBytes = gcnew array<Byte>(1500);
try
{
if (!IPAddress::TryParse(DestIpAddressString, address))
{
//Invalid IP Address
return;
}
byteId = 0;
sendBytes[byteId++] = ;
...
sendBytes[byteId++] = ;
//Transmit Packet
IPEndPoint ^Remote = gcnew IPEndPoint(address, REMOTE_UDP_SOCKET);
serverSocket->SendTo(sendBytes, byteId, System::Net::Sockets::SocketFlags::None, Remote);
}
catch (Exception ^)
{
}
Transmit Packet From Server Socket With Packet Sent Callback
IPAddress ^address;
int byteId;
array<Byte>^sendBytes = gcnew array<Byte>(1500);
try
{
if (!IPAddress::TryParse(DestIpAddressString, address))
{
//Invalid IP Address
return;
}
byteId = 0;
sendBytes[byteId++] = ;
...
sendBytes[byteId++] = ;
//Transmit Packet
IPEndPoint ^Remote = gcnew IPEndPoint(address, REMOTE_UDP_SOCKET);
serverSocket->BeginSendTo(sendBytes, 0, byteId, System::Net::Sockets::SocketFlags::None, Remote, gcnew AsyncCallback(this, &myClassName::OurSendCallback), serverSocket);
while (WaitingTxToComplete)
Threading::Thread::Sleep(20); //(Needed or deployment release version running from .exe will crash)
}
catch (Exception ^)
{
}
//*************************************
//*************************************
//********** UDP TX CALLBACK **********
//*************************************
//*************************************
void myClassName::OurSendCallback(IAsyncResult^ asyncResult)
{
serverSocket->EndSend(asyncResult);
WaitingTxToComplete = false;
}
Feel free to comment if you can add help to this page or point out issues and solutions you have found. I do not provide support on this site, if you need help with a problem head over to stack overflow.