C# packet structure system - c#

I am working on a packet system (UDP or TCP, either way is fine) but I came to the conclusion that my current (TCP) system is really awefull.
Basicly, I'm sending a packet that looks like this:
string packet = "LOGIN_AUTH;TRUE"
IPAddress target = IPAddress.Parse(endPoint);
// Send packet
When I recieve the packet in my client, I use this to determine the packet type:
string[] splitPacket = packet.Split(';');
if (splitPacket[0] == "LOGIN_AUTH" && splitPacket[1] == "TRUE")
authLogin(packet); //Does stuff like loading the next screen
But I'm sure there must be a better way to do this, because of this thread:
http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/79660898-aeee-4c7b-8cba-6da55767daa1/ (post 2)
I'm just wondering if someone could give me a push in the right direction on what I should to categorize the packets in a way that's more easy on the eye.
Thank you in advance.
Edit: I did some research, but I cant find a solution to my problem in WCF. So once again, what is the best way to create a packet structure, and how do I utilize it?
I don't want to recreate a protocol, just something like this:
public string sepChar = ";"
public static struct loginPacket
{
string type;
string username;
string password;
}
public void reqLogin()
{
lock (_locker) //Need to make it thread-safe in this case
{
loginPacket.type = "login";
loginPacket.username = "username";
loginPacket.password = "password;
sendPacket(loginPacket);
}
}
public void sendPacket(string packet)
{
// Script to send packet using the struct information
}
I hope that's detailed enough.

I would recommend WCF; if not now, decide to learn it in the future. It has a huge learning curve because it covers not only what you're trying to do, but so many other things.
If you just want a quick-and-dirty solution, then you could use binary serialization. To take this approach, you'll need to define your message types in a dll shared between client and server. Then, remember to use a form of message framing so that the messages don't get munged up in transit.
Things get more complex when you consider versioning. Eventually you'll want to use WCF.

I have used my own communication protocol over TCP 2 years ago, about the base packet class:
public enum PacketType {Login, Hello, FooBar}
public class Packet
{
public long Size;
public PacketType PacketType;
}
public class LoginPacket : Packet
{
public string Login;
public string Password;
}
I do not agree with Size property... because you will only know packet size AFTER it was serialized with binaryFormater. I have used other method, first i serialized packet object and then before putting this byte[] in network stream i wrote BitConverter.GetBytes(SerializedPacketMemoryStream.Length) before each packet bytes.
2nd thing to consider, is that you need to create temp buffer for received bytes[] and wait until you receive full packet and only then desirialize it.
I can send you my client\server code part, it's not very clean i wrote it when i just started learning C#, but it is 100% stable, tested for 3 years in production environment.

protobuf might be what you want.
Here's the .NET port: protobuf-net

Related

Receive UDP packet to Class. Design/Implementation assistance appreciated

I receive UDP data from localhost. This data needs to be used and kept track of. There could be >250k packets sent over the course of about 5 minutes. Currently, I create the IPEndPoint, and Receive the data. I then get the byte[] data into a string. Then I split the string into an array because the data is comma separated. From this array, I instantiate an object with the correct values from the array.
The incoming data has 4 properties and looks like this: ProductId=1284,Quantity=48623,Time=08:45:12.034,Date=2019-09-09
Currently I am able to Console.WriteLine the incoming packets, and cast each packet to an object (Product). Currently I do not store the data anywhere.
I need to monitor Quantity levels, and send alerts if the Quantity goes above or below certain thresholds. Secondly, I need to send another alert if the change in Quantity exceeds thresholds. This I will implement with if statements later and do not require assistance with at the moment. This alerts do need to be sent as UDP packets are received.
My questions are:
1) Should I implement this Asynchronously, or on a different thread?
2) Should I be sending the UDP Data directly to a Queue of type byte[], and then Dequeue each byte[] into an object? or keep instantiating new objects (or updating the quantity for each product) on the fly as the UDP data is received? Does Queue reduce the risk of dropped packets?
3) What is the best way to store each packet? To a List (This would keep everything in memory), a database (A bit beyond my current needs), or append each object to a text file (easy to write to, and can eventually build a database from)?
4) Is 250k packets over 5 minutes, and creating objects for all those packets considered a lot for a computer to handle?
Please advise if I can clarify anything. I apologize if any of my terminology is incorrect, I will learn and fix it. The coding I should be able to figure out on my own, it is the design and proper implementation that I am asking for guidance on. Thank you.
Below is code for setting up the UDP connection, and the class. I will be able to figure out the monitoring/messaging Quantity information after the UDP has been setup properly. I do have a Product Class not shown, it has several properties including ProductId, Quantity, Initial Quantity, Change in Quantity, Time and Date.
class Program
{
static void Main(string[] args)
{
int port = 22486;
var client = new UdpClient();
IPEndPoint localEp = new IPEndPoint(IPAddress.Any, port);
client.Client.Bind(localEp);
while (true)
{
try
{
byte[] data = client.Receive(ref localEp);
string text = Encoding.UTF8.GetString(data);
string[] message = text.Split(',', '=');
Product product = new Product();
product.ProductId = message[1];
product.Quantity = message[3];
}
catch (Exception err)
{
Console.WriteLine(err.ToString());
}
}
}
}
If you need to do other things while listening on that port, make it a thread.
queue it up in a byte array... a buffer of sorts.
Are azure blobs an option for you? you can use the storage emulator and if you change your mind about storing a file in blob, you can switch to table storage (this is like a nosql approach where you provide a partition name.)
No

C# Receiving Packet in System.Sockets with examples

in this qusetion C# Receiving Packet in System.Sockets
a guy asked:
"In my Client Server Application i wondered how to make a packet and send it to the server via the Client
Then on the server i recognize which packet is this and send the proper replay"
and showed the example of his way of implementing the 'packet recognizer'. He got an answer that his way of 'structuring the message' is bad, but no explanation and code example followed by the answer.
So please, can anybody show the example of a good code, which should do something like this, but proper way:
[client]
Send(Encoding.ASCII.GetBytes("1001:UN=user123&PW=123456")) //1001 is the ID
[server]
private void OnReceivePacket(byte[] arg1, Wrapper Client)
{
try
{
int ID;
string V = Encoding.ASCII.GetString(arg1).Split(':')[0];
int.TryParse(V, out ID);
switch (ID)
{
case 1001://Login Packet
AppendToRichEditControl("LOGIN PACKET RECEIVED");
break;
case 1002:
//OTHER IDs
break;
default:
break;
}
}
catch { }
}
TCP ensures that data arrives in the same order it was sent - but it doesn't have a concept of messages. For instance, say you send the following two fragments of data:
1001:UN=user123&PW=123456
999:UN=user456&PW=1234
On the receiving end, you will read 1001:UN=user123&PW=123456999:UN=user456&PW=1234 and this might take one, two or more reads. This may even arrive in two packets as:
1001:UN=user123&PW=12
3456999:UN=user456&PW=1234
This makes it very had to parse the message correctly. The other post mentions sending the length of a packet before the actual data, and that indeed solves the problem, as you can determine exactly when one message ends and the next starts.
As an example, client and server could agree that each message starts with 4 bytes containing the length of the message. The receiver could then simply:
load 4 bytes exactly
convert to an integer, now you know the length of the remainder of the message
read exactly that many bytes and parse the message
C# conveniently has the BitConverter class that allows you to convert the integer to a byte[] and vice versa.

C# Sockets - Sending a serialized object in a single packet

I'm stuck at the concept of TCP as a stream-oriented protocol.
While using Sockets or anything that uses that protocol there is no way to know how much data will be received in a single receive; so for example if we send 1024 bytes, it can be received in 3 Receive methods give or take.
So we basically need to keep calling our receive methods until the buffer hits the size sent.
I'm still struggling on network, I'm trying to get a bit comfortable using Client/Server applications. I found that the easiest way to do so is to create packets and send them over the network.
So my question is: When serializing a Class as a packet that has - lets say a typeof Normal.Message - and has a string that holds the Message...
[Serializable]
Class Message
{
String Msg;
public Message(String msg)
{
This.Msg = msg;
}
}
...if we sent this packet, is it undetermined that it will be received in one Receive Method? And if not, what's the easiest way to ensure that it will?

Lidgren Createmessage() Write() but Read() dynamic types, how?

I started to write my own networking with lidgren.
I am very far. My goal is to make later my own master server (lidgren has a example for that) and an auto matchmaking server which hosts server and closest again.
I am sick of Unity Networking (it's easy but limited), UNet and other things like photon. Photon is great but expensive for my plan.. and others do not have auto matchmaking... or they want to make it which still stays on server.
Well, I try to explain my idea and problem.
I want to make an dynamic serialize method which I want to call:
void OnULGNetworkSerialize(NetIncomingMessage msg)
The client can send very different things like int, float, bool, vector3, vector2 and so on.
The messages goes to server.. and the server need to send back to other clients. Clients has same code but the server not.
So how I can a solve this.
This part (server):
// Serializing
void OnULGNetworkSerialize(NetIncomingMessage msg)
{
int lenght = (int)msg.ReadByte();
for (int i = 1; i < lenght; i++)
{
// Read different types here
}
}
So if you look the code maybe you know what I want to try. The server or client have not always same message length and same types.
So how could I still get the type and send to all clients?

UDP sending data, something i don´t quite understand

Okay from my knowledge UDP works like this:
You have data you want to send, you say to the UDP client, hey send this data.
The UDP client then says, sure why not, and sends the data to the selected IP and Port.
If it get´s through or in the right order is another story, it have sent the data, you didn´t ask for anything else.
Now from this perspective, it´s pretty much impossible to send data and assemble it.
for example, i have a 1mb image, and i send it.
So i send divide it in 60kb files (or something to fit the packages), and send them one by one from first to last.
So in theory, if all get´s added, the image should be exactly the same.
But, that theory breaks as there is no law that tells the packages if it can arrive faster or slower than another, so it may only be possible if you make some kind of wait timer, and hope for the best that the arrive in the order they are sent.
Anyway, what i want to understand is, why does this work:
void Sending(object sender, NAudio.Wave.WaveInEventArgs e)
{
if (connect == true && MuteMic.Checked == false)
{
udpSend.Send(e.Buffer, e.BytesRecorded, otherPartyIP.Address.ToString(), 1500);
}
}
Recieving:
while (connect == true)
{
byte[] byteData = udpReceive.Receive(ref remoteEP);
waveProvider.AddSamples(byteData, 0, byteData.Length);
}
So this is basically, it sends the audio buffer through udp.
The receiving par just adds the udp data received in a buffer and plays it.
Now, this works.
And i wonder.. why?
How can this work, how come the data is sent in the right order and added so it appears as a constant audio stream?
Cause if i would to this with an image, i would probably get all the data.
But they would be in a random order probably, and i can only solve that by marking packages and stuff like that. And then there is simply no reason for it, and TCP takes over.
So if someone can please explain this, i just don´t get it.
Here is a code example that is when sending an image, and well, it works. But it seems to work better when the entire byte array isn´t sent, meanign some part of the image is corrupted (not sure why, probably something to do with how the size of the byte array are).
Send:
using (var udpcap = new UdpClient(0))
{
udpcap.Client.SendBufferSize *= 16;
bsize = ms.Length;
var buff = new byte[7000];
int c = 0;
int size = 7000;
for (int i = 0; i < ms.Length; i += size)
{
c = Math.Min(size, (int)ms.Length - i);
Array.Copy(ms.GetBuffer(), i, buff, 0, c);
udpcap.Send(buff, c, adress.Address.ToString(), 1700);
}
Receive:
using (var udpcap = new UdpClient(1700))
{
udpcap.Client.SendBufferSize *= 16;
var databyte = new byte[1619200];
int i = 0;
for (int q = 0; q < 11; ++q)
{
byte[] data = udpcap.Receive(ref adress);
Array.Copy(data, 0, databyte, i, data.Length);
i += data.Length;
}
var newImage = Image.FromStream(new MemoryStream(databyte));
gmp.DrawImage(newImage,0,0);
}
You should be using TCP. You write: it´s pretty much impossible to send data and assemble it. for example, i have a 1mb image, and i send it. So i send divide it in 60kb files (or something to fit the packages), and send them one by one from first to last. ... But, that theory breaks as there is no law that tells the packages if it can arrive faster or slower than another, so it may only be possible if you make some kind of wait timer, and hope for the best that the arrive in the order they are sent. That's exactly what TCP does: ensure that all the pieces of a stream of data are received in the order they were sent, with no omissions, duplications, or modifications. If you really want to re-implement that yourself, you should be reading RFC 793 - it talks at length about how to build a reliable data stream atop an unreliable packet service.
But really, just use TCP.
You're missing a lot of helpful details from your question, but based on the level of understanding presented I'll attempt to answer at a similar level:
You're absolutely right, in general the UDP protocol doesn't guarantee order of delivery or even delivery at all. Your local host is going to send the packets (i.e. parts of your request message) in the order it receives them from the sending application, and from there its up to network components to decide how your request gets delivered. In local networks however (within a handful of hops of the original requester) there aren't really a lot of directions for the packets to go. As such they will likely just flow in line and never see a hiccup.
On the greater internet however, there is likely a wide variety of routing choices available to each router between your requesting host and the destination. Every router along the way can make a choice on which direction parts of your message take. Assuming all paths are equal (which they aren't) and guaranteed reliability of every network segment between the 2 hosts its likely to see similar results as within network (with added latency). Unfortunately neither of the posed conditions can be considered reliable (different paths on the internet perform differently depending on client and server, and no single path on the internet should ever be considered to be reliable (that's why it's a "net").
These are of course based on general observations from my own experience in network support and admin roles. Members of other StackExchange sites may be able to provide better feedback.

Categories

Resources